记录 java Intertupt 取消任务失效

logicflow
• 阅读 439

每个线程对象里都有一个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里什么也不做。

点赞
收藏
评论区
推荐文章
Wesley13 Wesley13
3年前
java目前可以通过以下几种方式进行定时任务
1、单机部署模式Timer:jdk中自带的一个定时调度类,可以简单的实现按某一频度进行任务执行。提供的功能比较单一,无法实现复杂的调度任务。ScheduledExecutorService:也是jdk自带的一个基于线程池设计的定时任务类。其每个调度任务都会分配到线程池中的一个线程执行,所以其任务是并发执行的,互不影响。
Wesley13 Wesley13
3年前
java Future接口在logback的妙用
logback可以把N天的日志压缩成一个包(zip,gz),在压缩的时候logback采用后台异步线程的方式来实现,下面咱们就来看看Future接口在logback中的妙用。先来看下Future接口的全貌吧。publicinterfaceFuture<V{//取消任务booleancan
Wesley13 Wesley13
3年前
java 中断线程的几种方式 interrupt()
中断  中断(Interrupt)一个线程意味着在该线程完成任务之前停止其正在进行的一切,有效地中止其当前的操作。线程是死亡、还是等待新的任务或是继续运行至下一步,就取决于这个程序。虽然初次看来它可能显得简单,但是,你必须进行一些预警以实现期望的结果。你最好还是牢记以下的几点告诫。  首先,忘掉Thread.stop方法。虽然它确实停止了一个正
御弟哥哥 御弟哥哥
4年前
如何正确停止Java线程,终止Java线程的三种方法
如何正确停止Java线程,终止Java线程的三种方法在Java中有以下3种方法可以终止正在运行的线程:1.使用退出标志,使线程正常退出,也就是当run()方法完成后线程终止。2.使用stop()方法强行终止线程,但不推荐,该方法已被弃用,原因见后文。3.使用interrupt方法中断线程。以下内容翻译自J
Wesley13 Wesley13
3年前
Java并发多线程高频面试题
并发知识不管在学习、面试还是工作过程中都非常非常重要,看完本文,相信绝对能助你一臂之力。1、线程和进程有什么区别?线程是进程的子集,一个进程可以有很多线程。每个进程都有自己的内存空间,可执行代码和唯一进程标识符(PID)。每条线程并行执行不同的任务。不同的进程使用不同的内存空间(线程自己的堆栈),而所有
Wesley13 Wesley13
3年前
Java基础教程——线程池
启动新线程,需要和操作系统进行交互,成本比较高。使用线程池可以提高性能——线程池会提前创建大量的空闲线程,随时待命执行线程任务。在执行完了一个任务之后,线程会回到空闲状态,等待执行下一个任务。(这个任务,就是Runnable的run()方法,或Callable的call()方法)。Java5之前需要手动实现线程池,Java5之
Wesley13 Wesley13
3年前
Java(Android)线程池
介绍newThread的弊端及Java四种线程池的使用,对Android同样适用。本文是基础篇,后面会分享下线程池一些高级功能。1、newThread的弊端执行一个异步任务你还只是如下newThread吗?Java1234567newThread(newRunnable(){
Wesley13 Wesley13
3年前
Java多线程问题(下)
21、FutureTask是什么这个其实前面有提到过,FutureTask表示一个异步运算的任务。FutureTask里面可以传入一个Callable的具体实现类,可以对这个异步运算的任务的结果进行等待获取、判断是否已经完成、取消任务等操作。当然,由于FutureTask也是Runnable接口的实现类,所以FutureTask也可以放入线程池中
Wesley13 Wesley13
3年前
Java多线程:线程属性
\线程属性id:线程唯一标识。自动生成。不允许修改。name:线程的名字,可以自定义成有具体含义的名字,便于识别不同作用的线程。(可同名)isDaemon:是否是守护线程。true守护线程,false用
ThreadPoolExecutor线程池内部处理浅析 | 京东物流技术团队
我们知道如果程序中并发的线程数量很多,并且每个线程都是执行一个时间很短的任务就结束时,会因为频繁创建线程而大大降低系统的效率,因此出现了线程池的使用方式,它可以提前创建好线程来执行任务。本文主要通过java的ThreadPoolExecutor来查看线程池
小万哥 小万哥
1年前
深入理解 Java 多线程、Lambda 表达式及线程安全最佳实践
Java线程线程使程序能够通过同时执行多个任务而更有效地运行。线程可用于在不中断主程序的情况下在后台执行复杂的任务。创建线程有两种创建线程的方式。1.扩展Thread类可以通过扩展Thread类并覆盖其run()方法来创建线程:javapublicclas
logicflow
logicflow
Lv1
君家何处住,妾住在横塘。
文章
4
粉丝
0
获赞
0