Java线程中断的方法

现在多线程程序越来越多,如何安全地中断执行中的线程成了一个问题。比如之前的Thread.stop()方法现在就不推荐使用了。因为用这个方法会强制停止线程,当线程中有文件读取,数据库连接等,很可能得不到释放。

现在很多资料都推荐用Thread.interrupt()方法开实现线程中断。实际上Thread.interrupt()只是把线程标记为中断状态,它不会中断线程。程序员在需要中断的时候用Thread.isInterrupted()来判断是否为中断状态,然后在程序中断线程。

把线程用Thread.interrupt()标记为中断状态之后,该线程在调用Object.wait, Thread.join和Thread.sleep方法受阻时(即在调用上绪方法之前把线程用interrupt方法设置为中断状态),会抛出InterruptedException异常,并清除中断状态;该线程在可中断的通道上的 I/O 操作中受阻,则该通道将被关闭,然后抛出ClosedByInterruptException,FileLockInterruptionException或者其它中断异常(一般都是IOException的子类),但不会清除中断状态。

所以说,如果用Thread.interrupt()方法开断线程,虽然不会出现资源不释放的问题,但有可能和我们想像的结果不一致。当线程中有线程中断函数(Object.wait, Thread.join和Thread.sleep)或者有可中断的通道上的 I/O 操作的话,该方法有一定的不可知性。

一般来说,如果中断函数(Object.wait, Thread.join和Thread.sleep)或者有可中断的通道上的 I/O 操作之后的处理有或者没有都不会影响结果的话,可以直接用Thread.interrupt()方法来中断线程。但如果需求是中断线程之后,要求线程执行完本次操作之后再中断的话,我个人觉得自己添加一个中断标志是最好的。

以下程序是测试在用中断函数时是否会清除中断状态的代码。因为时间的不可控性,有时会在调sleep函数时抛出InterruptedException,这时线程就不会停止。这时可以再次调用 interrupt()或者直接用break退出线程。(I/O 操作的测试代码可以参考写)

Java
public class TestThreadSleep {
    public static void main(String[] avgs) throws InterruptedException {
        Thread th = new TestThreadSleep.ThreadDemo();
        th.start();
        System.out.println("Thread Started!");
        Thread.sleep(20);
        System.out.println("Main Sleeped!");
        th.interrupt();
        System.out.println("Thread Interrupted!");
        Thread.sleep(40);
        System.out.println("Main End!");
    }

    static class ThreadDemo extends Thread {
        public void run() {
            int count = 0;
            // 判断中断标记
            while (!isInterrupted()) {
                try {
                    sleep(10);
                    System.out.println("Thread Run Count:" + (++count));
                } catch (InterruptedException e) {
                    e.printStackTrace();
                    // 如果需要退出,可以再次调用 interrupt()
                    // 或者直接 break;
                }
            }
        }
    }
}

以下代码为自己添加中断标记的代码。

Java
public class TestThreadStop {
    public static void main(String[] avgs) throws InterruptedException {
        ThreadDemo th = new TestThreadStop.ThreadDemo();
        th.start();
        System.out.println("Thread Started!");
        Thread.sleep(20);
        System.out.println("Main Sleeped!");
        th.stopThread();
        System.out.println("Main Updated Stop Flag!");
        Thread.sleep(40);
        System.out.println("Main End!");
    }

    static class ThreadDemo extends Thread {
        private boolean stop = false;
        public void stopThread() {
            this.stop = true;
        }
        public void run() {
            int count = 0;
            // 判断中断标记
            while (!this.stop) {
                try {
                    sleep(10);
                    System.out.println("Thread Run Count:" + (++count));
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }
    }
}

转载请注明:宇托的狗窝 » Java线程中断的方法

发表我的评论
取消评论

Hi,您需要填写昵称和邮箱!

  • 昵称 (必填)
  • 邮箱 (必填)
  • 网址