如何正确中断 一个线程?

2,064 阅读3分钟

本文已参与「新人创作礼」活动,一起开启掘金创作之路

如何正确中断 一个线程?

1、通过线程提供的方法

  • interrupt
    通过调用此方法,系统就会给当前线程打上一个中断标记(true),默认为false,如果其他线程中调用当前线程中的此方法,表示告诉当前线程你可以停止了,当前线程也可以不理睬继续执行
  • isInterrupted 判断当前线程是否被中断,根据当前线程中断标志位,做相关的处理
  • Thread.interrupted() 判断线程是否被中断,此方法是个静态方法,跟isInterrupted 不同的是,在判断的之后会重置中断标记位为false
1.1 通过Thread 提供的方法来中断操作(建议使用)
 final Thread thread=new Thread("TestCustomisInterrupted"){
            @Override
            public void run() {
                super.run();
                //默认标志位 为false
                while (!isInterrupted()){
                    System.out.println(currentThread().getName()+"::::runing.......");
                }
                System.out.println("执行完成::::"+isInterrupted());  //true
            }
        };

        thread.start();
        try {
            Thread.sleep(2000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        thread.interrupt();

上边是个比较简单的例子,如果当前线程执行体里边有阻塞方法会是什么样的情况:

 final Thread thread=new Thread("TestCustomisInterrupted"){
            @Override
            public void run() {
                super.run();
                //默认标志位 为false
                while (!isInterrupted()){
                    try {
                        sleep(1000);
                        System.out.println(currentThread().getName()+"::::runing.......");
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
                System.out.println("执行完成::::"+isInterrupted());  //true
            }
        };

        thread.start();
        try {
            Thread.sleep(2000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        thread.interrupt();

输入结果

TestCustomisInterrupted::::runing.......
java.lang.InterruptedException: sleep interrupted
	at java.lang.Thread.sleep(Native Method)
	at com.example.socket.MyClass$1.run(MyClass.java:78)
TestCustomisInterrupted::::runing.......
TestCustomisInterrupted::::runing.......
TestCustomisInterrupted::::runing.......

会抛出一个中断异常,并且把中断标志为重置为false,线程不会停止会一直执行,如果想让程序继续执行中断操作可以在,异常里边继续设置中断操作

利用Thread.interrupted() 静态方法判断,如果发生中断之后,会直接把中断标记位设置为fasle

  final Thread thread=new Thread("TestCustomisInterrupted"){
            @Override
            public void run() {
                super.run();
                //默认标志位 为false
                while (!Thread.interrupted()){
                        System.out.println(currentThread().getName()+"::::runing.......");
                }
                System.out.println("执行完成::::"+isInterrupted());  //true
            }
        };

        thread.start();
        try {
            Thread.sleep(2000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        thread.interrupt();

TestCustomisInterrupted::::runing.......
TestCustomisInterrupted::::runing.......
执行完成::::false

2、通过线程自定义字段去终止线程

 class MyRunable implements Runnable{
            boolean isRun=true;

            public boolean isRun() {
                return isRun;
            }

            public void setRun(boolean run) {
                isRun = run;
            }

            @Override
            public void run() {
                while (isRun){
                    System.out.println("::::runing.......");
                }
                System.out.println("执行完成::::"+isRun);  //true
            }
        }
        MyRunable myRunable=new MyRunable();
       new Thread(myRunable).start();
        try {
            Thread.sleep(2000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        myRunable.setRun(false);


::::runing.......
::::runing.......
::::runing.......
::::runing.......
::::runing.......
执行完成::::false

使用自定义标记也可以来停止线程,那和线程提供的方法有什么不一样的呢? 加入我们的run方法逻辑中有阻塞方法时候

        class Mythread extends Thread{
            boolean isRun=true;

            public boolean isRun() {
                return isRun;
            }

            public void setRun(boolean run) {
                isRun = run;
            }
            @Override
            public void run() {
                super.run();
                while (isRun()){
                    try {
                        Thread.sleep(4000);
                        System.out.println("::::runing.......");
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
                System.out.println("执行完成::::"+isRun());  //true
            }
        }

        Mythread mythread=new Mythread();
        mythread.start();
        try {
            Thread.sleep(1000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        mythread.setRun(false);

加入sleep方法之后,发现在线程休眠的时候调用的mythread.setRun(false); 线程不会马上停止,会等到休眠时间到了执行完run方法之后,才会停止

3、使用线程的 stop、suspend、resume 方法

以上三个是thread 提供的方法,但是现在被标注过期,不建议 使用,是因为使用以上方法,停止线程系统不会释放线程所占有的资源,因为没有给线程释放资源的机会和时间,会引起其他问题,所以不建议使用。