本文最后更新于2 分钟前,文中所描述的信息可能已发生改变。
两阶段终止含义
即分为两个阶段来终止线程,让线程自然的结束
run
方法。第一个阶段是线程t1
向需要终止的t2
线程发送终止请求,第二个阶段是t2
线程响应中断请求,即自然的结束run
方法。可以采用调用线程的实例方法interrupt()
与自定义的中断标志位来先让线程从sleep
状态变为Runnable
进而变为Terminated
状态正常结束run
方法。
简单的示例
java
public void stopMode() throws InterruptedException {
Thread thread1 = new Thread(() -> {
Thread th = Thread.currentThread();
while (!th.isInterrupted()){
try {
System.out.println("执行逻辑..");
//每隔一秒执行一次
TimeUnit.SECONDS.sleep(1);
} catch (InterruptedException e) {
e.printStackTrace();
//重置打断标记为true,使得线程正确终止
th.interrupt();
}
}
});
thread1.start();
TimeUnit.SECONDS.sleep(5);
//主线程给t1发送打断请求
thread1.interrupt();
}
更加优雅点的示例
java
public class Test{
//自定义线程是否结束的标志位
// 因为这样可以在不管有没有正常处理中断异常,都能使得线程正常结束
private volatile boolean shutDown = true;
private Thread thread;
public void start(){
if(shutDown){
shutDown = false;
thread = new Thread(()->{
//为什么不使用thread.isInterrupted()来判断线程是否要执行中断
while (!shutDown){
try {
work();
TimeUnit.SECONDS.sleep(1);
} catch (InterruptedException e) {
//抛出处理中断异常后JVM会重置中断标志位
e.printStackTrace();
//加了自定义标志位thread.interrupt()有没有都不影响线程结束
//因为是使用的是自定义标志位来进行判断
thread.interrupt();
}
}
});
thread.start();
}
}
private void work(){
System.out.println("执行业务逻辑..");
}
public boolean isShutDown(){
return shutDown;
}
public void shutDown(){
//给其他线程调用,发送一个中断线程的请求
//更改标志位
shutDown = true;
if(thread!=null){
//发送设置中断标志位为true
thread.interrupt();
}
}
}
静态方法Thread.interrupted()
与实例方法isInterrupted()
的区别
都是用于判断当前线程是否被打断,静态方法Thread.interrupted()
不仅会读取打断标志的值还会重置该打断标志为false
而实例方法isInterrupted()
则是只读打断标志的值。
小结
通过两阶段终止模式可以优雅的停止线程,防止结束线程时未释放锁而发生死锁等问题。
参考文章