3 Terminal of Thread(线程终止)
2019-11-02 本文已影响0人
Vander1991
3.1 线程终止简介
线程终止顾明思议,我们在线程运行期间,有时候需要在某些条件下,让线程停止运行,并且目标线程只有在被阻塞(此处的阻塞不是指线程的BLOCKED状态)的情况下才能被终止。
有以下两种:
1、如果目标线程在调用Object.wait(long)、Object.wait(long, int)、join()、join(long, int)、sleep(long, int)方法被阻塞,那么interrupt会生效,该线程的中断状态将被清除,抛出InterruptedException异常。
2、如果目标线程是被I/O或者NIO中的Channel所阻塞,同样,I/O操作会被中断或者返回特殊异常值。达到终止线程的目的。
让线程中断的方式就是使用thread.Interrupt或者使用标志位。
3.1.1 方式一:使用Interrupt终止线程
StopThread.java:
public class StopThread extends Thread {
private int i = 0, j = 0;
@Override
public void run() {
synchronized (this) {
// 增加同步锁,确保线程安全
++i;
try {
// 休眠10秒,模拟耗时操作
Thread.sleep(10000);
} catch (InterruptedException e) {
e.printStackTrace();
}
++j;
}
}
public void print() {
System.out.println("i=" + i + " j=" + j);
}
}
InterruptThread.java:
public class InterruptThread {
public static void main(String[] args) throws InterruptedException {
StopThread thread = new StopThread();
thread.start();
// 休眠1秒,确保i变量自增成功
Thread.sleep(1000);
// 暂停线程
// thread.stop(); // 错误的终止
thread.interrupt(); // 正确终止
while (thread.isAlive()) {
// 确保线程已经终止
} // 输出结果
thread.print();
}
}
运行结果:可以观察到挂住1秒之后就出结果了,说明线程被中断成功了
运行结果
线程在接收到Interrupt指令的时候,会抛出异常,这样也能让你的应用程序在finally中进行一些资源的回收关闭等操作。
3.1.2 方式二:使用标志位终止线程
/** 通过状态位来判断 */
public class FlagInterruptThread extends Thread {
public volatile static boolean flag = true;
public static void main(String[] args) throws InterruptedException {
new Thread(() -> {
try {
while (flag) { // 判断是否运行
System.out.println("运行中");
Thread.sleep(1000L);
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}).start();
// 3秒之后,将状态标志改为False,代表不继续运行
Thread.sleep(3000L);
flag = false;
System.out.println("程序运行结束");
}
}
运行结果:
运行结果
3.2 错误的线程终止
在早期的JDK中,还有使用Stop来进行线程终止,使用Stop来进行线程终止最大的问题就是造成了线程的不安全性,就拿上面这段代码为例,Stop会在线程处于wait状态的时候,接收到Stop指令就直接把线程干掉了,本来上面的那段代码里面用了关键字synchronized来保证线程的安全性,线程直接被终止了就会导致i++了但是j却还没有进行加1操作。这里值得一提的是,如果用stop来终止线程,但是你代码里面有finally的语句块,finally的语句块还是会执行的。(目前不用Stop来终止线程,所以这也不用太关心)。