目录
1、不正确的线程中止
2、正确的线程中止
2.1、interrupt
2.2、标志位
更多内容,请关注我的博客
1、不正确的线程中止
stop为不正确的线程中止方式,并且清楚监控器锁的信息,但是可能导致线程安全问题,目前jdk不建议使用。
Destroy:JDK未实现该方法。
下面我们使用一段测试代码来验证stop的不正确性:
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();
}
System.out.println("----模拟耗时结束------");
++j;
}
}
//打印i和j的值
public void print(){
System.out.println("i=" + i + ",j=" + j);
}
}
测试代码:
public static void main(String[] args) throws InterruptedException {
StopThread stopThread = new StopThread();
stopThread.start();
//休眠1秒,确保变量i自增成功
Thread.sleep(1000);
//中止线程
stopThread.stop();
while (stopThread.isAlive()){
//确保线程已经终止
}
//打印结果
stopThread.print();
}
StopThread 线程运行后,目的是对全局变量i和j的值都自增1,在主线程中对该线程stop后的结果如下:
i=1,j=0
显然stopThread线程被中止后,sleep后面的代码都没有再被执行。导致程序最终结果并不是我们想要的结果,因为理想值应该i=1且j=1。
2、正确的线程中止
2.1、interrupt
中断在java中主要有3个方法,interrupt(),isInterrupted()和interrupted()。
- interrupt(),在一个线程中调用另一个线程的interrupt()方法,即会向那个线程发出信号——线程中断状态已被设置,只是中断状态被改变(设置为true),该线程并不会被中断或者中止,并不像stop会直接中断线程的执行。
- isInterrupted(),用来判断当前线程的中断状态(true or false)。
- interrupted()是个Thread的static方法,用来恢复中断状态,并返回当前中断状态。
如果目标线程在调用Object class的wait()、wait(long)或者wait(long,int)方法、join、join(long,int)或者sleep(long,int)方法时被阻塞,那么Interrupt会生效,该线程的中断将被清楚,抛出InterruptedException异常。
如果目标线程被I/O或者NIO的Channel所阻塞,同样I/O操作会被中断或者返回特殊常值。达到终止线程的目的。
如果以上条件都不满足,则这时调用interrupt方法将不起作用,只是线程的中断状态设置为true而已,该线程所执行的程序还是会正常执行。
如果将stop换成interrupt,main方法如下:
public static void main(String[] args) throws InterruptedException {
StopThread stopThread = new StopThread();
stopThread.start();
//休眠1秒,确保变量i自增成功
Thread.sleep(1000);
//中止线程
//stopThread.stop();
stopThread.interrupt();
while (stopThread.isAlive()){
//确保线程已经终止
}
//打印结果
stopThread.print();
}
代码执行结果如下:
----模拟耗时结束------
i=1,j=1
java.lang.InterruptedException: sleep interrupted
at java.lang.Thread.sleep(Native Method)
at cn.sunnymaple.javabase.threadstop.StopThread.run(StopThread.java:18)
注意此时的结果不仅达到了我们预期的结果i=1,j=1,而且还抛出了InterruptedException异常,说明使用interrupt会抛出异常,让用户决定异常后如何处理,而不是像stop一样强行终止程序。
2.2、标志位
通过标志位,数值或者boolean,代码如下:
public class FlagStopThreadTest {
private volatile static boolean flag = true;
public static void main(String[] args) throws InterruptedException {
new Thread(()->{
try {
while (flag){
System.out.println("运行中");
Thread.sleep(1000);
}
}catch (InterruptedException e){
e.printStackTrace();
}
}).start();
Thread.sleep(3000);
flag = false;
System.out.println("程序运行结束");
}
}