线程中止
- stop 中止线程,并且清除监控器的信息,但可能导致线程安全问题。JDK不建议使用
- Destroy:JDK未实现该方法
- interrupt:优雅的方式中断线程
- 标志位:正确的线程中止
利用Demo演示线程中止状态
package com.study.basejava.a1_thread_status;
/**
* 示例3 - 线程stop强制性中止,破坏线程安全的示例
*/
public class Demo3 {
public static void main(String[] args) throws InterruptedException {
StopThread thread = new StopThread();
thread.start();
// 睡眠1s 确保变量自增成功
Thread.sleep(1000L);
// 暂停线程
thread.stop(); // 错误的终止
// thread.interrupt();
while (thread.isAlive()){
System.out.println("线程的状态"+thread.getState().toString());
// 确保线程已经终止
}
// 输出结果
thread.print();
}
}
package com.study.basejava.a1_thread_status;
public class StopThread extends Thread {
private int i = 0, j = 0;
@Override
public void run() {
synchronized (this){ // 原子性操作,保证线程操作不受到其他线程的干扰 正常返回结果:i 和 j 打印相同
// 增加同步锁,确保线程安全
++i;
try {
// 睡眠10秒,模拟耗时操作
Thread.sleep(10000);
}catch (InterruptedException e){
e.printStackTrace();
}
++j;
}
}
/**
* 打印i和j
*/
public void print() {
System.out.println("i=" + i + " j=" + j);
}
}
在启动上述Demo中,理论上最终打印的 i 和 j 的数据是一致的。
- 错误的中止方式 - stop:如果线程在睡眠期间被stop掉,会导致 i 和 j 打印的数据不一致,我们用synchronized保证原子性的目标是没有达成的,破坏了线程的线程安全。原因:利用stop停止线程,会致使正在运行的程序从中间拦腰折断,导致 i 的自增成功,j 的自增失败。这种中止线程的方式,严重的违反了我们设计线程的用意。
- 正确的线程中止 - Interrupt
如果目标线程在调用Object class的wait()、wait(Long)或者wait(Long,int)方法,join、join(Long、int)或sleep(long,int)方法被阻塞,那么Interrupt会生效,改线程的中端状态将被清除,抛出InterruptedException异常
如果目标线程是被I/O或者NIO中的Channel所阻塞,同样,I/O操作会被中断或者返回特殊异常值。达到中止线程的目的。
如果以上条件都不满足,则会设置此线程的中断状态。
将上述实例中的stop改成Interrupt后,最终输出 i 和 j 的值相同,数据一致。 - 标志位中断线程
如果代码逻辑中是一个循环执行的业务,可以增加一个判断,用来控制线程执行的中止,受限于代码执行的逻辑。如 Demo4:
package com.study.basejava.a1_thread_status;
public class Demo4 {
public volatile static boolean flag = true;
public static void main(String[] args) throws InterruptedException {
new Thread(()->{
try {
while (flag){ // 判断是否运行
System.out.println("运行中"+Thread.currentThread().getState().toString());
Thread.sleep(1000L);
}
}catch (InterruptedException e){
e.printStackTrace();
}
}).start();
// 3秒之后,将状态标志改为False,代表不继续运行
Thread.sleep(3000L);
flag = false;
System.out.println("程序运行结束"+Thread.currentThread().getState().toString());
}
}
原文作者: 小呆呆
原文链接
版权声明: 转载请注明出处(必须保留作者署名及链接)