结束线程方法2 Java提供的中断机制

package com.mozq.thread.interrupt;
/**
 *     注意:调用interrupt()方法,并不会结束线程。
 *     结束线程的语义:需要我们自己使用3个中断方法构建。
 * 
 * 没有任何语言方面的需求一个被中断的线程应该终止。
 * 中断一个线程只是为了引起该线程的注意,被中断线程可以决定如何应对中断。
 * 某些线程非常重要,以至于它们应该不理会中断,而是在处理完抛出的异常之后继续执行。
 * 但是更普遍的情况是,一个线程将把中断看作一个终止请求,这种线程的run方法遵循如下形式
public void run() {
    try {
        ...
         * 不管循环里是否调用过线程阻塞的方法如sleep、join、wait,这里还是需要加上
         * !Thread.currentThread().isInterrupted()条件,虽然抛出异常后退出了循环,显
         * 得用阻塞的情况下是多余的,但如果调用了阻塞方法但没有阻塞时,这样会更安全、更及时。
        while (!Thread.currentThread().isInterrupted()&& more work to do) {
            do more work 
        }
    } catch (InterruptedException e) {
        //线程在wait或sleep期间被中断了
    } finally {
        //线程结束前做一些清理工作
    }
}

上面是while循环在try块里,如果try在while循环里时,因该在catch块里重新设置一下中断标示,
因为抛出InterruptedException异常后,中断标示位会自动清除,此时应该这样:
public void run() {
    while (!Thread.currentThread().isInterrupted()&& more work to do) {
        try {
            ...
            sleep(delay);
        } catch (InterruptedException e) {
            Thread.currentThread().interrupt();//重新设置中断标示
        }
    }
}

 *     结束线程方法2:interrupt()方法,interrupted()方法和isInterrupted()方法
 *     该方法的中断语义详细定义在说明文档中。和通常所说的中断意思不一致。
 *     interrupt()方法用于设置:
 *         如果线程处于wait,sleep,join阻塞,则会发生中断异常。中断状态为被清除。
 *         一般情况则导致中断状态位被设置
 *     isInterrupted()检测不清除
 *     interrupted()检测并清除。
 *     通过这3个方法,适用于一个线程向另一个线程发送信息,并被B线程处理。
 *     可以用来实现线程A根据情况结束线程B的语义。
 *     
 *     分成2种情况,1.线程处于阻塞状态2.线程处于正常运行
 *     线程处于正常运行
 * public class ThreadSafe extends Thread {
        public void run() { 
            while (!isInterrupted()){
                //do something, but no throw InterruptedException
            }
        } 
    }
    线程处于阻塞状态
    public class ThreadSafe extends Thread {
        public void run() { 
            while (!isInterrupted()){ //非阻塞过程中通过判断中断标志来退出
                try{
                    Thread.sleep(5*1000);//阻塞过程捕获中断异常来退出
                }catch(InterruptedException e){
                    e.printStackTrace();
                    break;//捕获到异常之后,执行break跳出循环。
                }
            }
        } 
    }
1
 * @author jie
 *
 */
public class MyInterruptMethod {
    public static void main(String[] args) {
        Thread t = new Thread() {
            //方法1:
            /*
            @Override
            public void run() {
                try {
                    while(!Thread.currentThread().isInterrupted()) {
                        System.out.println(Thread.currentThread().getName() + "...run");
                        Thread.sleep(100);
                    }
                } catch (InterruptedException e) {}
            }
            */
            @Override
            public void run() {
                    while(!Thread.currentThread().isInterrupted()) {
                        System.out.println(Thread.currentThread().getName() + "...run");
                        try {
                            Thread.sleep(10);
                        } catch (InterruptedException e) {
                            //因为虚拟机处理interrupt调用时,如果方法处于阻塞,会抛出异常并清除中断标志,所以此处需要重置。
                            Thread.currentThread().interrupt();
                            //return;
                            //break;
                        }
                    }
            }
            
        };
        t.start();
        try {
            Thread.sleep(100);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        //业务逻辑。。。
        //此处想结束线程
        t.interrupt();
    }
}

 

posted @ 2019-02-21 17:45  没有理由不会呀  阅读(186)  评论(0编辑  收藏  举报