`
xuexing
  • 浏览: 24028 次
  • 性别: Icon_minigender_1
  • 来自: 成都
社区版块
存档分类
最新评论

Java Thread中的interrupt方法使用详解

阅读更多
Thread.interrupt() 使用不当,导致程序无法退出(转)

原文出处:http://blog.chenlb.com/2009/07/incorrect-use-thread-interrupt-cause-not-exit.html

Java Thread.interrupt() 使用不当,导致多线程程序无法正常退出。前段时间写的一个多线程程序:一个子线程基本是死循环地从任务池里取出任务(取的时候,没有任务会阻塞),并运行可用的任务。没有任务了,完成的时候 main 线程调用子线程的中断,抓到中断后退出子线程的死循环。

上面的程序已经正常的运行了几个月了,是一天运行一次而已。近期要在每4分钟运行一次的应用中使用了这程序。运行一天多就会阻塞掉了(一直不会退出),今天是第二次了。观察分析日志:是在 main 调用 taskThread.interrupt() 会没有输出日志(实际就是没有中断到子线程),而死循环是在接受到中断才会把循环条件设为 false。所以程序 block了,不退出了。

分析:调用 taskThread.interrupt() 为什么没有接受到中断(实际是 InterruptedException)呢?找原理:Thread.interrupt() 的调用对正在运行的线程是不起作用的,只有对阻塞的线程有效。下面是引用:Java Thread.interrupt 害人! 中断JAVA线程(zz) 的一段重要的话。

    使用Thread.interrupt()中断线程

    Thread.interrupt()方法不会中断一个正在运行的线程。这一方法实际上完成的是,在线程受到阻塞时抛出一个中断信号,这样线程就得以退出阻塞的状态。更确切的说,如果线程被Object.wait, Thread.join和Thread.sleep三种方法之一阻塞,那么,它将接收到一个中断异常(InterruptedException),从而提早地终结被阻塞状态。

    因此,如果线程被上述几种方法阻塞,正确的停止线程方式是设置共享变量,并调用interrupt()(注意变量应该先设置)。如果线程没有被阻塞,这时调用interrupt()将不起作用;否则,线程就将得到异常(该线程必须事先预备好处理此状况),接着逃离阻塞状态。在任何一种情况中,最后线程都将检查共享变量然后再停止。

程序代码块大概:

   1. public void run() { 
   2.     while(running) { 
   3.         Object obj = null; 
   4.         try { 
   5.             //... 
   6.             //取出数据 
   7.             obj = taskQueue.take(); 
   8.             //执行任务... 
   9.         } catch (InterruptedException e) { 
  10.             running = false; 
  11.             log.info("被 interrupt, 退出"); 
  12.         } 
  13.  
  14.     }   //while 
  15.     //.... 
  16. } 

public void run() {
while(running) {
Object obj = null;
try {
//...
//取出数据
obj = taskQueue.take();
//执行任务...
} catch (InterruptedException e) {
running = false;
log.info("被 interrupt, 退出");
}

} //while
//....
}

描述现在的程序:使子线程阻塞的地方是从任务池取数据,具体来说是 java.util.concurrent.LinkedBlockingQueue.take() 方法。它在 try/catch 内,catch 到 InterruptedException 设置执行任务的循环条件变量。然后就退出 run。我草率地认为interrupt被调用了(认为take会被阻塞,有一段每200ms检测全部任务是否完成),一定能 catch 到中断。也没有在调用 taskThread.interrupt() 之前把循环条件变量设为 false。所以造成有时候子线程不能退出。

当执行最后一个任务还没有完成时,main 调用 taskThread.interrupt() 就会失效,因为子线程没有 blocking。

解决办法是在调用 interrupt 之前,running = false。
分享到:
评论

相关推荐

    java线程中的interrupt,isInterrupt,interrupted方法

    java 线程中的 interrupt,isInterrupt,interrupted 方法详解 在 Java 中,线程(Thread)类提供了三个相关的方法:interrupt、isInterrupted 和 interrupted,这三个方法都是用于处理线程的中断状态的。下面我们将...

    Java多线程详解

    推荐使用interrupt()方法来中断线程,并在run()方法中检查isInterrupted()或interrupted()状态,以优雅地退出线程。 六、线程池 Java提供ExecutorService和ThreadPoolExecutor等工具类来管理线程池,可以有效地复用...

    java线程中断之interrupt和stop.docx

    ### Java线程中断机制详解:`interrupt`与`stop`方法 #### 一、引言 在Java多线程编程中,线程控制是至关重要的技术之一。有时我们需要在特定条件下停止某个线程的执行,或者中断正在等待的线程。Java提供了多种...

    Java多线程之中断线程(Interrupt)的使用详解

    `Thread.interrupt()`方法是中断线程的主要手段,但它的行为并不像字面意义上那样直接终止线程。相反,它通过设置线程的中断状态来向线程发送一个中断信号,这个信号是一个内部标志,告知线程应该停止其当前的工作。...

    java安全停止线程的方法详解

    在 Java 中,Thread.stop() 方法是一个被废弃的方法,不被推荐使用的原因是该方法太过于暴力,强行把执行到一半的线程终止,并且会立即释放这个线程所有的锁。这将破坏了线程中引用对象的一致性。 使用判断标志位的...

    java多线程高级设计模式详解

    Java的`Thread.interrupt()`方法可以用来中断线程。通常在循环中检查`Thread.currentThread().isInterrupted()`来响应中断请求。中断不是立即停止线程,而是设置一个标志,线程需要自己处理中断请求。 九、线程局部...

    java多线程编程详解

    `Thread.interrupt()`方法可以请求线程中断,但不会立即停止线程。线程需要在适当位置检查`Thread.currentThread().isInterrupted()`,并在可能的情况下结束。 9. **守护线程(Daemon)**: 守护线程在所有非守护...

    java Thread

    - `wait()`和`notify()`/`notifyAll()`:用于线程间的通信,需在同步环境中使用。 - `ReentrantLock`:可重入锁,提供更灵活的同步控制,支持公平锁与非公平锁。 5. **线程中断与异常处理** - `interrupt()`:...

    Java多线程详解及示例

    Thread类提供了interrupt()方法用于中断线程,但需要注意的是,这并不意味着线程会立即停止,而是在线程检查到中断标志后自行决定是否停止。守护线程(Daemon Thread)是一种特殊线程,当所有非守护线程结束时,守护...

    详解Java中Thread 和Runnable区别

    详解Java中Thread和Runnable区别 Java中Thread和Runnable是两个不同的概念,它们都是Java中的线程机制,但是它们之间有着本质的区别。 Thread是Java中的一个类,而Runnable是一个接口。Thread类实现了Runnable接口...

    java中的多线程实例详解(自己去运行看结果)

    Java提供了一些线程控制方法,如`sleep()`使线程休眠,`join()`等待线程结束,`yield()`让当前线程暂停,以及`interrupt()`中断线程。 同步机制防止多个线程同时访问共享资源,Java提供了以下几种方式: 1. `...

    Java多线程编程详解

    它们必须在`synchronized`代码块或方法中使用,以确保正确操作。 3. **线程状态**:Java线程有新建、可运行、运行、阻塞和终止五种状态。理解这些状态对于调试和优化多线程程序至关重要。 4. **线程优先级**:Java...

    java多线程设计模式详解

    Java提供了`Thread.interrupt()`方法来中断线程,但需要注意的是,中断并不立即停止线程,而是设置一个中断标志。线程需要检查这个标志并相应地处理中断请求。 以上是Java多线程设计模式的一些核心概念和应用实例。...

    java多线程Thread的实现方法代码详解

    Thread类是Java中用于实现线程的基础,提供了多种方法来控制线程的行为。本篇文章将详细解析Thread类中的start()、run()、stop()、interrupt()、isInterrupted()、join()以及join(long millis)等方法。 1. **start...

    Java多线程的用法详解

    在Java中,创建线程主要有两种方法: **方法一:继承Thread类** 当一个类继承自Thread类,就可以重写run()方法来定义线程执行的任务。然后通过调用start()方法启动线程。以下是一个简单的例子: ```java public ...

    java+多线程+同步详解源代码学习

    - wait()、notify()和notifyAll():在同步块或同步方法中使用,用于线程间的通信。必须在持有对象锁的情况下调用,否则会抛出IllegalMonitorStateException。 - Condition接口:Lock接口的一个实现类提供,提供了...

    Java 多线程编程详解.pdf

    继承Thread类的方法直接在新线程中运行覆盖的run()方法,而实现Runnable接口则需要将run()方法包含的对象传递给Thread的构造函数,然后启动新线程。 接着,文档会深入探讨线程的生命周期,包括新建、就绪、运行、...

    JAVA多线程设计模式详解

    10. 可中断线程模式:线程在执行过程中可以被其他线程中断,例如通过Thread.interrupt()方法。 11. 信号量模式:Semaphore类提供了一种控制同时访问特定资源的线程数量的方法,用于限流或同步。 12. 计数器模式:用...

    java面试题题库详解

    - **Thread 类没有 destroy() 方法:** Java 中没有直接销毁线程的方法。 - **线程终止方式:** 使用 `interrupt()` 或者让线程正常结束。 #### 15. Thread.stop()、Thread.suspend() 的问题 **知识点概述:** - *...

    java多线程之停止线程的方法实例代码详解

    总结以上所述,Java多线程之停止线程的方法实例代码详解可以使用退出标记、interrupt()方法和interrupted()方法来停止线程。使用退出标记停止线程简单易行,但需要对线程的执行过程进行控制。使用interrupt()方法和...

Global site tag (gtag.js) - Google Analytics