首页 > 编程语言 > 详细

多线程02

时间:2021-04-06 20:38:22      阅读:25      评论:0      收藏:0      [点我收藏+]

1.java中定义的线程状态,及它们之间的转换关系?

1新建(new)

2可运行(Ruannable).start

3阻塞状态( BLOCKED ) :可运行状态遇到了锁

4.等待状态(WAITING):遇到了wait方法

5.计时等待( TIMED_WAITING):遇到了sleep方法

6.死亡状态( TERMINATED):进程结束变成垃圾

2.什么线程池?

存放线程的容器

3.线程池的原理?

创建一个线程池,里面是空的,当有任务需要执行时,才会创建线程对象,当对象执行完毕时,线程对象归还给线程池

4.为什么要使用线程池?

避免为了频繁创建线程造成资源浪费,可以提高体统的效率

5.如何创建线程池?

自动创建(不推荐): Executors new ThreadPoolExecutor

使用Executors中所提供的静态方法来创建线程池

static ExecutorService newCachedThreadPool() 创建一个默认的线程池 ? static ExecutorService newFixedThreadPool(int nThreads) 创建一个指定最多线程数量的线程池

5.1参数列表代表什么意思?

手动创建: ThreadPoolExecutor (七个参数)

参数一:核心线程的数目 不能小于0

参数二:最大线程数目 不能小于0 最大数目>=核心线程数

参数三:空闲线程的最大存活时间 不能小于0

参数四:空闲线程的最大存活时间单位 不能为null

参数五:任务队列(一般使用ArrayBlockingQueue)因为有限制线程数量 不能为null

参数六:创建线程工厂 不能为null

参数七:拒绝策略 不能为null

5.2 线程池的运行规则?

参数一:核心线程数量,线程池中初始线程数,刚刚创建ThreadPoolExecutor的时候,线程并不会立即启动,而是要等到有任务提交时才会启动 当线程数超过核心线程数时,会将请求的任务放入任务队列 参数二:最大线程数,当任务队列满时,如果线程数没有超过最大线程数时,创建新的线程 参数三:空闲线程最大存活时间 参数四:时间单位---TimeUnit 参数五:任务队列 --- 当线程数超过核心线程数量小于最大线程数时,让任务在队列中等着,等有线程空闲了,再从这个队列中获取任务并执行 参数六:创建线程工厂 --- 按照默认的方式创建线程对象 参数七:任务的拒绝策略 --- 1.什么时拒绝? 当提交的任务 > 池子中最大的线程数量+队列的容量 //2.如何拒绝? 拒绝策略

6.线程安全的本质-可见性、原子性、有序性

可见性:多个线程同时访问一个共享变量时,其中一个线程对静态变量进行修改,其他进程能够立刻获得修改后的值(volatiel关键字或者上锁可以解决)

原子性:操作是不能中断的,线程要不全部执行成功,要不全部执行失败()

有序性:编译器和处理器为了优化性能而对指令序列进行重新排序,就是编写的代码执行的顺序和编写的不一致

6.1java中原子性操作

1.除了long和double以外的全部基本数据类型(long和double因为字节数都是64位,以前的计算机都是32位,需要合并)

2.volatiel变量的赋值

3.java.concurrent.Atomic *类的所有操作

6.1 什么是Java内存模型?

java内存模型是一种虚拟的存在,并不是真实存在的,它描述的是一种规范或者规则,通过这种规则定义了程序中的共享变量(包括实例(对象)字段,静态字段和构成数组对象的元素)的访问方式

6.2 认识不认识JMM?

JMM就是JAVA内存模型,JMM规定1.每个线程中操作共享变量都只能在自己的工作内存中操作,不能再主存中直接读写 2.不同线程不能直接访问其他线程工作内存中的变量,线程中变量值的传递只能通过主存进行。(可以对比CPU->Cache->内存)

6.3 Java如何解决线程可见性?

synchronized :1.线程加锁时,将清除线程工作内存中共享变量的数据,直接从主存中读取数据进程操作 2.线程释放锁时,将共享变量的最新值存储到主存中

volatile:线程写数据的时候,JMM会把共享变量的最新值存到主存中,线程读数据的时候,JMM会把线程中的工作内存中的共享变量制为无效,并把主存中的最新值赋给线程中的工作内存。 ?

6.4 Java中是如何解决原子性问题?

synchronized

CAS

6.4.1原子性_AtomicInteger

1.什么是原子操作类?

原子操作类提供了一种用法简单,性高效,线程安全的更新一个变量的方式(原子基本数据类型,原子更新数组,原子更新引用,原子更新属性(字段))

2.如何使用原子的方式更新基本类型?

AtomicBoolean: 原子更新布尔类型

AtomicInteger: 原子更新整型

AtomicLong: 原子更新长整型

3.AtomicInteger的常用方法:

方法说明
public AtomicInteger() 初始化一个默认值为0的原子型Integer
public AtomicInteger(int initialValue) 初始化一个指定值的原子型Integer
int get() 获取值
int getAndIncrement() 以原子方式将当前值加1,注意,这里返回的是自增前的值。
int incrementAndGet() 以原子方式将当前值加1,注意,这里返回的是自增后的值。
int addAndGet(int data) 以原子方式将输入的数值与实例中的值(AtomicInteger里的value)相加,并返回结果
int getAndSet(int value) 以原子方式设置为newValue的值,并返回旧值

代码实现 :

7.并发工具包

7.1 并发容器
  1. 1.Hashtable :HashMap的线程是不安全的,为了保证数据的安全性,但是效率比较低

  2. 1.Hashtable的特点:1.采用悲观锁synchronized保证数据安全 2.只要有线程访问,会把整个表锁起来

 

2.1ConcurrentHashMap:保证线程的安全性和效率

7.2 并发工具类

7.2.1CountDownLatch

让一条线程等待,等别的线程都结束在执行

原理:

  • CountDownLatch是通过一个计数器来实现的,计数器的初始值为需要等待线程的数量。

eg:CountDownLatch c = new CountDownLatch(10); // 等待线程的数量为10

  • 线程调用CountDownLatch的await()方法会阻塞当前线程(即:主线程在闭锁上等待),直到计数器的值为0。

  • 当一个工作线程完成了自己的任务后,调用CountDownLatch的countDown()方法,计数器的值就会减1。

  • 当计数器值为0时,说明所有的工作线程都执行完了,此时,在闭锁上等待的主线程就可以恢复执行任务

 

7.2.2Semaphore

可以控制资源的访问线程数量

原理:

  • Semaphore是通过一个计数器(记录许可证的数量)来实现的,计数器的初始值为需要等待线程的数量

  • eg:Semaphore s = new Semaphore(10); // 线程最大的并发数为10

  • 线程通过acquire()方法获取许可证(计数器的值减1),只有获取到许可证才可以继续执行下去,否则阻塞当前线程

  • 线程通过release()方法归还许可证(计数器的值加1)

多线程02

原文:https://www.cnblogs.com/zhangmeng0726/p/14623306.html

(0)
(0)
   
举报
评论 一句话评论(0
关于我们 - 联系我们 - 留言反馈 - 联系我们:wmxa8@hotmail.com
© 2014 bubuko.com 版权所有
打开技术之扣,分享程序人生!