线程的中断
1.线程的死亡(终止状态):run()方法执行结束返回。中断的作用就是中断run()方法中的阻塞,使run()方法执行结束返回。。
2.不可中断的阻塞是危险的。
参考:
https://www.cnblogs.com/yangming1996/p/7612653.html
线程各生命周期状态下执行中断时:
new 与 terminated:
线程的new状态表示还未调用start方法,还未真正启动。
线程的terminated状态表示线程已经运行终止。
此时的中断操作没有任何意义,什么事情也不会发生。
RUN状态
1 设置中断标记
2 因为线程没有被阻塞,索引不会有任何中断产生。
此时中断的意义,体现在,设置了中断标记后,可以由程序员决定退出线程,而不抛出任何异常
public void run(){
while(true){
if (Thread.currentThread().isInterrupted()){
System.out.println("exit MyThread");
break;
}
}
}
Block 阻塞状态
sleep引起的阻塞:可响应中断、可中断的阻塞
1 设置中断标记
2 中断阻塞状态,并抛出InterruptException异常
3 清除中断标记
wait引起的阻塞: 可响应中断、可中断的阻塞
1 设置中断标记
2 中断阻塞状态,并抛出InterruptException异常
3 清除中断标记
等待输入输出的IO操作引起的阻塞: 部分响应中断、不可中断的阻塞
1 设置中断标记
2 不中断阻塞、也不会抛出异常
等待锁引起的阻塞:部分响应中断、不可中断的阻塞
1 设置中断标记
2 不中断阻塞、也不会抛出异常
对于以上阻塞状态下发生的中断,正确的处理方法:
1 sleep引起的阻塞: catch InterruptException异常
2 wait引起的阻塞: catch InterruptException异常
3 IO引起的阻塞: 下发中断后要主动关闭IO资源,则阻塞状态自然解除。
4 等待锁引起的阻塞: 使用ReentranLock加锁----可中断的阻塞。
一个典型的通用场景:
class NeedsCleanUp {
private final int id;
NeedsCleanUp(int id){
this.id = id;
System.out.println("NeedsCleanUp " + id);
}
public void cleanup() {
System.out.println("Clean up " + id);
}
}
class MyTask implements Runnable{
private volatile double d = 0.0;
@Override
public void run() {
// TODO Auto-generated method stub
try {
while(!Thread.currentThread().isInterrupted()) { //用于处理未阻塞态的中断
NeedsCleanUp n1 = new NeedsCleanUp(1); //需要申请资源与释放资源的操作
try {
TimeUnit.SECONDS.sleep(1);//引起阻塞的操作
NeedsCleanUp n2 = new NeedsCleanUp(2);
try {
for(int i = 0 ; i < 2500000; i++) {
d = d + (Math.PI + Math.E) / d; //耗时操作
}
}finally {
n2.cleanup();//释放资源
}
}finally {
n1.cleanup();//释放资源 阻塞操作被中断后 在这里释放资源
}
}
}catch(InterruptedException e) {
System.out.println(e.getMessage()); //阻塞态度中断后抛出异常
}
}
}