java多线程技术: interrupt() 中断线程, 优雅停止线程及原理

MyThread.class

package cn.yilong.edcsapiservice.thread;

public class MyThread extends Thread {
    @Override
    public void run() {
        System.out.println("开始睡觉");
        try {
            Thread.sleep(10);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println("结束睡觉");

        synchronized (MyThread.class){
            for (int i=0; i<100; i++){
                System.out.print(i+",");
            }
            System.out.println();
            String name = Thread.currentThread().getName();
            System.out.println(name + ": " + this.isInterrupted());
            System.out.println("test--------------------");
            System.out.println();
        }

    }
}

Run.class

package cn.yilong.edcsapiservice.thread;

public class Run2 {

    public static void main(String[] args) {
        Thread ct = Thread.currentThread();
        ct.setName("mainThread");

        try {
            MyThread t = new MyThread();
            t.setName("myThread");
            t.start();

            t.interrupt();  // 如果t线程已经结束,再调中断方法,不做任何处理

            synchronized (MyThread.class) {
                String name = Thread.currentThread().getName();
                System.out.println(name + ": " + t.interrupted()); //虽然是t线程调用,但底层真正调用不是t,而是当前main方法的线程, 执行实际操作是 Thread.currentThread().isInterrupted() 即mainThread线程
                System.out.println(t.getName() + ": " + t.isInterrupted()); 
                System.out.println("main-----------------------------");
                System.out.println();
            }


        } catch (Exception e) {
            System.out.println("main catch");
            e.printStackTrace();
        }
    }
}



mainThread: false
myThread: true
main-----------------------------

 
 

开始睡觉
java.lang.InterruptedException: sleep interrupted
at java.lang.Thread.sleep(Native Method)
at cn.yilong.edcsapiservice.thread.MyThread.run(MyThread.java:8)
结束睡觉
0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,
myThread: false
test--------------------



interrupt() 方法

interrupt()本质是 给调用该方法的线程做一个标记, 这个标记默认初始值是: false, 调用后变成: true,  
所以说, 做标记并不能停止这个线程.  而废弃的stop()方法是直接停止这个线程. 这是根本区别.

线程对象调用interrupt()方法时, 我们想中断这个线程, 需要人为写逻辑进行中断,  
通常存在两种情况(实际还有其他,源码注释上有解释):
1. 线程状态:正在运行中,  此时如果t线程调用了interrupt()方法,  那么,t线程会立刻被做上标识: false变为true,  (当然,如果t线程调用interrupt()前刚好正常执行结束了,
那么标记不会变更,依然时false) t线程如果还在执行中, 依然继续执行下去, 被标记不会受到任何影响(重点), 接着,我们在t线程的执行方法run()中通过调用 interrupted()或
isInterrupted()来进行手动结束run()方法的执行. 啰嗦下: (
1) t.interrupt()执行后, 打标记: false变true, run()方法中 t.interrupted()和t.isInterrupted()会获取到这个标记,值为false或true. (2) t.interrupted()方法注意两点:
1.指代当前调用的线程, 也就是说, 如果在mian()方法中, 执行了t.interrupted()方法, 实际执行的并不是t线程, 而是main线程(特别注意)
2.t.interrupted()方法执行后,会返回一个结果true或false, 同时它还会执行另一步操作: 将t线程标记的结果重置为默认初始值: false. 所以,不要第二次调用它.(特别注意)
(3) t.isInterrupted()方法指的就是t线程的中断标记: true,或false, 它只返回结果, 不会做其他的操作.

2. 线程状态: 阻塞中, 比如调用了sleep(), 或wait(), 或join() 阻塞方法, 此时如果t线程调用了interrupt()方法, 那么,t线程会立刻被做上标识: false变为true, 同时,
阻塞中的t线程此时监测到自己中断标识变为了true, 便抛出了InterruptedException异常, 同时, 将t线程标记的结果重置为默认初始值: false (重点).
接着,我们在t线程的执行方法run()中通过try--catch捕获该异常,然后手动处理结束run()方法.

猜你喜欢

转载自www.cnblogs.com/smileblogs/p/11563554.html