天天看点

线程中止1、不正确的线程中止2、正确的线程中止

目录

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("程序运行结束");
    }
}
           

继续阅读