多线程
线程池的状态

线程池的5种状态:Running、ShutDown、Stop、Tidying、Terminated
Running:(1) 状态说明:线程池处在RUNNING状态时,能够接收新任务,以及对已添加的任务进行处理。
(2) 状态切换:线程池的初始化状态是RUNNING。换句话说,线程池被一旦被创建,就处于RUNNING状态,并且线程池中的任务数为0!
ShutDown:(1) 状态说明:线程池处在SHUTDOWN状态时,不接收新任务,但能处理已添加的任务。
(2) 状态切换:调用线程池的shutdown()接口时,线程池由RUNNING -> SHUTDOWN。
Stop:(1) 状态说明:线程池处在STOP状态时,不接收新任务,不处理已添加的任务,并且会中断正在处理的任务。
(2) 状态切换:调用线程池的shutdownNow()接口时,线程池由(RUNNING or SHUTDOWN ) -> STOP。
(2) 状态切换:当线程池在SHUTDOWN状态下,阻塞队列为空并且线程池中执行的任务也为空时,就会由 SHUTDOWN -> TIDYING。
当线程池在STOP状态下,线程池中执行的任务为空时,就会由STOP -> TIDYING。
TERMINATED:(1) 状态说明:线程池彻底终止,就变成TERMINATED状态。
(2) 状态切换:线程池处在TIDYING状态时,执行完terminated()之后,就会由 TIDYING -> TERMINATED。
线程的启动和创建
线程在操作系统的真正创建是调用了start方法后,才会进行创建;
new Thread();进行了初始化,当调用start()方法,会调用本地方法start0(),进行jvm 的线程创建,通过jvm 的线程创建,进而创建操作系统的线程创建。
sleep和wait的区别
1、这两个方法来自不同的类分别是Thread和Object。
2、最主要是sleep方法没有释放锁,而wait方法释放了锁,使得其他线程可以使用同步控制块或者方法。
3、wait,notify和notifyAll只能在同步控制方法或者同步控制块里面使用,而sleep可以在。
wait和notify配合syncronized一起使用的原因
如果 wait 和 notify/notifyAll 不强制和 synchronized 一起使用,那么在多线程执行时,就会出现 wait 执行了一半,然后又执行了添加数据和 notify 的操作,从而导致线程一直休眠的缺陷。
class MyBlockingQueue { // 用来保存数据的集合 Queue<String> queue = new LinkedList<>(); /** * 添加方法 */ public void put(String data) { // 队列加入数据 queue.add(data); // 唤醒线程继续执行(这里的线程指的是执行 take 方法的线程) notify(); // ③ } /** * 获取方法(阻塞式执行) * 如果队列里面有数据则返回数据,如果没有数据就阻塞等待数据 * @return */ public String take() throws InterruptedException { // 使用 while 判断是否有数据(这里使用 while 而非 if 是为了防止虚假唤醒) while (queue.isEmpty()) { // ① // 没有任务,先阻塞等待 wait(); // ② } return queue.remove(); // 返回数据 } }
我们在代码中标识了三个关键执行步骤:①:判断队列中是否有数据;②:执行 wait 休眠操作;③:给队列中添加数据并唤醒阻塞线程。如果不强制要求添加 synchronized,那么就会出现如下问题:
| 步骤 | 线程1 | 线程2 |
|---|---|---|
| 1 | 执行步骤 ① 判断当前队列中没有数据 | |
| 2 | 执行步骤 ③ 将数据添加到队列,并唤醒线程1继续执行 | |
| 3 | 执行步骤 ② 线程 1 进入休眠状态 |
如果 wait 和 notify 不强制要求加锁,那么在线程 1 执行完判断之后,尚未执行休眠之前,此时另一个线程添加数据到队列中。然而这时线程 1 已经执行过判断了,所以就会直接进入休眠状态,从而导致队列中的那条数据永久性不能被读取,这就是程序并发运行时“执行结果混乱”的问题。
wait和notify为啥用while不用if
https://www.cnblogs.com/ibcdwx/p/13733874.html
如果是if,它不会进行二次判断;所以wait使用要在while内,while会一直判断是否符合条件。
nofiyAll()方法调用时,不知道哪条线程不该被唤醒,所以需要再次进行判断。

浙公网安备 33010602011771号