记录 java Intertupt 取消任务失效

2年前 (2022) 程序员胖胖胖虎阿
235 0 0

每个线程对象里都有一个boolean类型的标识(可以叫做中断标识),代表着是否有中断请求,可以使用这个标志位实现线程的终止功能。在最近的一个任务取消的功能时,写下来如下代码:

        Thread t = new Thread(new Runnable() {
            @Override
            public void run() {
                while (!Thread.interrupted()) {
                    try {
                        System.out.println("I am ok");
                        Thread.sleep(500);
                    } catch (Exception e) {
                        logger.warn(...);
                    }
                }
            }
        });
        t.start();
     

然后在程序中适当的时机调用了 t.interupt()。满怀期待任务的停止。but意外发生了,任务打印出了"java.lang.InterruptedException: sleep interrupted"日志后,任务任然继续运行。
很显然中断标识被清除了。

查看sleep方法的说明中有以下内容:

InterruptedException - if any thread has interrupted the current thread. The interrupted status of the current thread is cleared when this exception is thrown.

sleep 发生InterruptedException 后,中断标识被清除 。顺便我们看看InterruptedException的说明:

Thrown when a thread is waiting, sleeping, or otherwise occupied, and the thread is interrupted, either before or during the activity. Occasionally a method may wish to test whether the current thread has been interrupted, and if so, to immediately throw this exception. The following code can be used to achieve this effect:

if (Thread.interrupted())
   throw new InterruptedException();

当线程等待、休眠或以其他方式被占用,并且线程在活动之前或期间被中断时抛出。 有时某个方法可能希望测试当前线程是否已被中断,如果是,则立即抛出此异常。 下面的代码可以用来实现这个效果

if (Thread.interrupted())
   throw new InterruptedException();

修改原来的代码,捕获InterruptedExceion 并进行处理:

 Thread t = new Thread(new Runnable() {
            @Override
            public void run() {
                while (!Thread.interrupted()) {
                    try {
                        System.out.println("I am ok");
                        Thread.sleep(500);
                    } catch (InterruptedException e) {
                        Thread.currentThread().interrupt();
                    } catch (Exception e) {
                        e.printStackTrace();
                    }
                }
            }
        });
        t.start();

运行后可以interupt后 可以实现取消功能。

总结: 当有InterruptException 发生时,要进行处理,抛出异常或者再次标记中断标识。
特别是方法是给别人调用的最好不要吞掉中断,即捕获到InterruptedException后在catch里什么也不做。

版权声明:程序员胖胖胖虎阿 发表于 2022年11月2日 上午11:08。
转载请注明:记录 java Intertupt 取消任务失效 | 胖虎的工具箱-编程导航

相关文章

暂无评论

暂无评论...