内容简介:线程池生命周期包括:转换成TIDYING状态的线程会运行terminated方法。执行完terminated()方法之后,所有等待在awaitTermination()就会返回。转换过程为:
线程池生命周期包括:
- RUNNING:接收新的任务并处理队列中的任务
- SHUTDOWN:不接收新的任务,但是处理队列中的任务
- STOP:不接收新的任务,不处理队列中的任务,同时中断处理中的任务
- TIDYING:所有的任务处理完成,有效的线程数是0
- TERMINATED:terminated()方法执行完毕
转换成TIDYING状态的线程会运行terminated方法。执行完terminated()方法之后,所有等待在awaitTermination()就会返回。
转换过程为:
线程池是空的即有效线程数是0
取消
如果代码能够在某个操作正常完全之前置入“完成”状态,那么这个操作就称为可取消的。java中提供了协作式机制,使请求取消的任务和代码遵循一种协商好的协议。
线程中断
线程中断就是一种协作机制。它并不会真正的中断一个正在运行的线程,而只是发出中断请求,然后由线程在下一个合适的时刻中断自己。
Thread中的中断方法包括
interrupt
public void interrupt() { if (this != Thread.currentThread()) checkAccess();//非当前线程有可能抛出SecurityException synchronized (blockerLock) { //用于执行可终端的IO操作对应的方法 Interruptible b = blocker; if (b != null) { //仅设置终端标记 interrupt0(); //执行实现了Interruptible接口的防范 b.interrupt(this); return; } } //仅设置终端标记 interrupt0(); } 复制代码
调用它根据线程的不同场景,有不同的结果
-
如果线程阻塞的是一个可以终端的channel,那么channel会被关闭,同时线程会收到java.nio.channels.ClosedByInterruptException,并且会设置中断标志
//AbstractInterruptibleChannel中: protected final void begin() { if (interruptor == null) { interruptor = new Interruptible() { public void interrupt(Thread target) { synchronized (closeLock) { if (!open) return; open = false; interrupted = target; try { //关闭channel AbstractInterruptibleChannel.this.implCloseChannel(); } catch (IOException x) { } } }}; } blockedOn(interruptor); Thread me = Thread.currentThread(); if (me.isInterrupted()) interruptor.interrupt(me); } 复制代码
-
如果线程阻塞在Selector,执行它的 wakeup方法,因而selector会立即返回,同时会设置中断标志
//AbstractSelector中: protected final void begin() { if (interruptor == null) { interruptor = new Interruptible() { public void interrupt(Thread ignore) { //执行wakeup,Selector立即返回 AbstractSelector.this.wakeup(); }}; } AbstractInterruptibleChannel.blockedOn(interruptor); Thread me = Thread.currentThread(); if (me.isInterrupted()) interruptor.interrupt(me); } 复制代码
-
如果线程阻塞在wait/join/sleep,线程的中断标志会被清除,并抛出InterruptedException
-
非上述三种情况,仅设置中断标志
可以看出调用interrupt并不意味着立即停止目标线程正在进行的工作,而只是传递了请求中断的消息
interrupted
清除当前线程的中断状态,并返回之前的值。它实际执行的就是当前线程的isInterrupted(true)
public static boolean interrupted() { return currentThread().isInterrupted(true); } 复制代码
假设当前线程是中断的,此时调用会返回true,如果在下次调用之前没有中断,此时调用会返回false
isInterrupted
返回目标线程的中断状态,只有线程状态是中断才会返回true,其它时候返回false
public boolean isInterrupted() { return isInterrupted(false); } 复制代码
可以看到interrupted和isInterrupted 调用的都是isInterrupted方法,只不过参数不一样。它的参数实际代表的是是否要清除中断标记,为true也就清除,在 java 中的定义如下
private native boolean isInterrupted(boolean ClearInterrupted); 复制代码
参考 linux 上的实现为 ``` bool os::is_interrupted(Thread* thread, bool clear_interrupted) { assert(Thread::current() == thread || Threads_lock->owned_by_self(), "possibility of dangling Thread pointer"); OSThread* osthread = thread->osthread(); bool interrupted = osthread->interrupted(); if (interrupted && clear_interrupted) { osthread->set_interrupted(false); //如果中断了,并且要清除中断标记,就改变终端标记 // consider thread->_SleepEvent->reset() ... optional optimization } return interrupted; } ``` 复制代码
响应中断 - 处理InterruptedException
一般策略如下
- 传递异常,使当前方法也成为可中断的
- 恢复中断状态,使得调用栈中的上层代码能够对其进行处理
处理不可中断的阻塞
并非所有的可阻塞方法或者阻塞机制都能响应中断,停止线程的方法类似于中断
- Java.io中的Socket I/O。InputStream和OutputStream中的read和write等不会响应中断,可以关闭底层的套接字抛出SocketException
- Java.io中的同步I/O。大多数的标准的channel都实现了InterruptibleChannel,它内部一般都是抛出ClosedByInterruptException,并关闭链路
- Selector的异步I/O。阻塞在了Selector.select,通过调用wakeup或者close来提前返回。
- 获取某个锁。由于线程等待某个内置锁,它会认为自己能等到,所以不会处理中断,通过Lock的lockInterruptibly可以同时实现等待锁并且响应中断
Thread.stop本身是不安全的。停止一个线程会释放它所有的锁的监视器,如果有任何一个受这些监视器保护的对象出现了状态不一致,其它的线程也会以不一致的状态查看这个对象,其它线程在这个对象上的任何操作都是无法预料的 为什么废弃了Thread.stop
关闭
应用程序准备退出时,这些服务所拥有的线程也应该结束。 ExecutorService提供了两种方法:shutdown和shutdownNow
- shutdown在执行完队列中的所有任务之后,才关闭,它并不会接收新的任务
- shutdownNow则是立马关闭正在执行的任务,并返回还没有开始的任务
以上就是本文的全部内容,希望本文的内容对大家的学习或者工作能带来一定的帮助,也希望大家多多支持 码农网
猜你喜欢:- Java 多线程(三)—— 线程的生命周期及方法
- Java并发 -- 线程生命周期
- Java线程生命周期深入理解
- Java线程生命周期与状态切换
- Java线程生命周期这样理解挺简单的
- Java并发编程(01):线程的创建方式,状态周期管理
本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。
Is Parallel Programming Hard, And, If So, What Can You Do About
Paul E. McKenney
The purpose of this book is to help you understand how to program shared-memory parallel machines without risking your sanity.1 By describing the algorithms and designs that have worked well in the pa......一起来看看 《Is Parallel Programming Hard, And, If So, What Can You Do About 》 这本书的介绍吧!