`

【解惑】 中断线程Interrupted的用处

阅读更多

★ 线程状态

       Java虚拟机将线程运行过程分成四种状态 。 (1) New 新生;(2) Runnable 可运行;(3) Blocked 阻塞;(4) Dead 死亡。

      值得注意的是: 线程的可运行状态并不代表线程一定在运行(runnable != running ) 。 大家都知道:所有现代桌面和服务器操作系统都使用了抢占式的线程调度策略 。一旦线程开始执行,并不是总是保持持续运行状态的。当系统分给它的时间片(非常小的运行时间单位)用完以后,不管程序有没有执行完,线程被强制放弃CPU,进入就绪状态,直到下次被调度后开始继续执行。也就是说, Runnable可运行状态的线程处于两种可能的情况下:(1)占用CPU运行中,(2)等待调度的就绪状态。 这里要声明一下:处于等待调度的就绪状态线程和处于阻塞的线程是完全不同的。就绪的线程是因为时间片用完而放弃CPU,其随时都有可能再次获得CPU而运行,这一切取决于分时OS的线程调度策略。

       在很多操作系统的专业术语中,这种因时间片用完而被剥夺CPU的情况我们叫做线程中断 。注意这和我们下面要将得中断线程是两个完全不同的概念。事实上,我们不可能通过应用程序来控制CPU的线程中断,除非我们能够自由调用OS的内核。


中断线程 —— interrupt()

       一个正在运行的线程除了正常的时间片中断之外,能否被其他线程控制?或者说其他线程能否让指定线程放弃CPU或者提前结束运行? 除了线程同步机制之外,还有两种方法:
       (1) Thread.stop(), Thread.suspend(), Thread.resume() 和Runtime.runFinalizersOnExit() 这些终止线程运行的方法 。这些方法已经被废弃,使用它们是极端不安全的。
       (2) Thread.interrupt() 方法是很好的选择。但是使用的时候我们必须好好理解一下它的用处。

 //无法中断正在运行的线程代码  
 class TestRunnable implements Runnable{  
       public void run(){  
             while(true)  
             {  
                   System.out.println( "Thread is running..." );  
                   long time = System.currentTimeMillis();//去系统时间的毫秒数  
             while((System.currentTimeMillis()-time < 1000)) {  
                    //程序循环1秒钟,不同于sleep(1000)会阻塞进程。  
             }  
               }  
        }  
 }  
 public class ThreadDemo{  
          public static void main(String[] args){  
                Runnable r=new TestRunnable();  
                Thread th1=new Thread(r);  
                th1.start();  
                th1.interrupt();           
         }  
 }  
//运行结果:一秒钟打印一次Thread is running...。程序没有终止的任何迹象 

      上面的代码说明interrupt()并没有中断一个正在运行的线程,或者说让一个running中的线程放弃CPU。那么interrupt到底中断什么。

       首先我们看看interrupt究竟在干什么。

       当我们调用th1.interrput()的时候,线程th1的中断状态(interrupted status) 会被置位。我们可以通过Thread.currentThread().isInterrupted() 来检查这个布尔型的中断状态。

        在Core Java中有这样一句话:"没有任何语言方面的需求要求一个被中断的程序应该终止。中断一个线程只是为了引起该线程的注意,被中断线程可以决定如何应对中断 "。好好体会这句话的含义,看看下面的代码:

 //Interrupted的经典使用代码  
 public void run(){  
         try{  
              ....  
              while(!Thread.currentThread().isInterrupted()&& more work to do){  
                     // do more work;  
              }  
         }catch(InterruptedException e){  
                     // thread was interrupted during sleep or wait  
         }  
         finally{  
                    // cleanup, if required  
         }  
 }  

       很显然,在上面代码中,while循环有一个决定因素就是需要不停的检查自己的中断状态。当外部线程调用该线程的interrupt 时,使得中断状态置位。这是该线程将终止循环,不在执行循环中的do more work了。

       这说明: interrupt中断的是线程的某一部分业务逻辑,前提是线程需要检查自己的中断状态(isInterrupted())。

       但是当th1被阻塞的时候,比如被Object.wait, Thread.join和Thread.sleep三种方法之一阻塞时。调用它的interrput()方法。可想而知,没有占用CPU运行的线程是不可能给自己的中断状态置位的。这就会产生一个InterruptedException异常。

 //中断一个被阻塞的线程代码
class TestRunnable implements Runnable{
     public void run(){
          try{
	    Thread.sleep(1000000); //这个线程将被阻塞1000秒
       }catch(InterruptedException e){
	     e.printStackTrace();
                     //do more work and return.
          }
     }
}
public class TestDemo2{
      public static void main(String[] args) {
            Runnable tr=new TestRunnable();
            Thread th1=new Thread(tr);
            th1.start(); //开始执行分线程
        while(true){
	   th1.interrupt();  //中断这个分线程
        }
      }
}
/*运行结果:
   java.lang.InterruptedException: sleep interrupted
        at java.lang.Thread.sleep(Native Method)
        at TestRunnable.run(TestDemo2.java:4)
        at java.lang.Thread.run(Unknown Source)*/

 

 

分享到:
评论
3 楼 honey_fansy 2017-03-15  
有点明白了
2 楼 clausewitzer 2011-11-04  
感谢,非常有帮助。
1 楼 shinestarwang 2010-05-03  
<div class="quote_title">使用finally要注意:</div>
<div class="quote_title">Heart.X.Raid 写道</div>
<div class="quote_div">
<p><span style="font-size: small;">       finally子句是不得不执行的。也正是由于它的这个特点,我们常常在程序异常跳出之前执行一些回收资源的动作。用Java编写的数据库程序就是很好的例子,我们总是要在程序中断前关闭所有与数据库的连接的。</span> </p>
<p><span style="font-size: small;">       finally子句的作用不容忽视,有了finally,是不是我们可以在程序结束前执行任何我们想执行的语句呢?也并非这样,有两类语句写在finally块中是需要好好斟酌的。</span> </p>
<p><span style="font-size: small;">      (1) return 语句</span> <span style="font-size: small;">public int f(int n){ try{ int r=n*n; return r; } finally{ if(n==2) return 0; //危险 } }
<pre></pre>
<p>        其中try中的return r;是没有任何作用的,因为在调用的方法返回之前必须执行方法中的finally子句。这样执行到return 0;其实该方法就结束了。比如我们调用f(2),结果返回的一定是0,这样原始值4就被忽略了。这种代码的清晰度是很差的。</p>
<p>        (2)   抛出异常语句</p>
InputStream in=....; try{ x(); //有可能抛出了非IOException } catch(IOException e){ e.printStackTrace(); } finally{ in.close(); //如果这里抛出了一个异常,就危险了 }
<pre></pre>
<p>         假设try块中的方法x()抛出了一个FileNotFoundException,而catch块捕捉的却是IOException异常。也就是说这个时候程序应该终止,并抛出FileNotFoundException,但是别忘了还有一个finally块必须先执行,好了,这个时候意外发生了,in.close()也出现异常了,并且抛出了一个IOException,没办法,开始的那个FileNotFoundException会丢失,结果只会抛出IOException而终止程序。</p>
<p> </p>
<p>        这两个问题怎么解决呢?其实也好办,就是尽量不要在finally块中写这两种语句,除非你明确不会出问题。</p>
<span style="font-size: small;">
<p> </p>
</span></span></p>
<p> </p>
</div>
<p> </p>

相关推荐

    Java 实例 - 中断线程源代码+详细指导教程.zip

    在Java编程中,中断线程是一项重要的任务,它允许程序在必要的时候停止或者结束一个正在运行的线程。本教程的压缩包包含了中断线程的源代码实例和详细指导,旨在帮助开发者深入理解和掌握这一核心概念。以下是关于...

    java中断线程的正确姿势完整示例.rar

    在Java编程中,中断线程是一项重要的任务,特别是在多线程环境下,我们可能需要停止某个线程的执行,以优化程序资源的使用或响应特定的系统需求。本示例将详细探讨Java中断线程的正确方法,以确保线程安全且高效地...

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

    要中断线程,需要在 run 方法中检查中断状态标志,并根据需要退出或中断线程。 isInterrupted 方法 isInterrupted 方法用于检查线程的中断状态标志。该方法返回当前线程的中断状态标志。如果该线程的中断状态标志...

    JAVA多线程之中断机制stop()、interrupted()、isInterrupted()

    当外部请求中断线程时,内部的`isInterrupted()`检查会发现中断状态,从而使循环结束。这种方式允许线程在完成当前任务或清理工作后优雅地退出,而不是立即停止执行。 总结来说,Java多线程的中断机制通过`...

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

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

    Android中断线程的处理方法

    中断线程的处理是确保应用响应性和用户体验的关键。本篇将详细讲解如何在Android中正确地中断线程,以及处理中断后的工作。 首先,Android中的线程中断主要是通过`Thread.interrupted()`或`Thread.currentThread()....

    Java多线程笔记

    Java多线程笔记是 Java 编程语言中关于多线程编程的笔记,涵盖了线程基础知识、线程优先级、线程状态、守护线程、构造线程、线程中断等多方面的内容。 获取简单 main 程序中的线程 在 Java 中,可以使用 ...

    Java中断线程的方法

    在Java中,中断线程主要是通过调用`Thread`对象的`interrupt()`方法来实现的。这个方法并不会立即停止目标线程,而是设置一个中断标志,表明线程已被请求中断。如果线程处于阻塞状态(例如在`sleep()`, `wait()`, ...

    理解多线程,写一个多线程应用程序,要求能在用户级实现线程的调度,如启动、挂起、恢复、停止,的C thread、java thread实现。

    Java中,`join`方法有类似功能,而`interrupt`方法可以用来中断线程,通常配合`isInterrupted`或`interrupted`检查中断状态。 在实际应用中,线程调度还需要考虑线程同步和互斥问题,以防止数据竞争和死锁。C语言中...

    Java多线程中断机制三种方法及示例

    从源码可以看到,`interrupted()`方法实际上调用的是当前线程的`isInterrupted(true)`方法,该方法用于测试当前线程的中断状态。 3. `isInterrupted()`方法 `isInterrupted()`方法是用来测试当前线程是否已经中断...

    java多线程的讲解和实战

    9. **线程中断**:`interrupt()`方法可以标记线程中断状态,线程可以通过检查`isInterrupted()`或`interrupted()`方法来响应中断请求,从而优雅地停止线程执行。 10. **线程局部变量(ThreadLocal)**:为每个线程...

    Thread类的interrupt(),interrupted(),isInterrupted()1

    在Java多线程编程中,理解`Thread`类中的`interrupt()`、`interrupted()`和`isInterrupted()`方法至关重要,因为它们与线程中断机制紧密相关。线程中断是Java提供的一种协作式中断机制,它并不强制结束线程,而是...

    java多线程编程实例

    - `interrupt()`方法用于请求中断线程。但是,这并不立即停止线程的执行,而是改变线程的中断状态。 - `interrupted()`和`isInterrupted()`方法用于检查线程是否已被中断。`interrupted()`方法会清除中断状态,而`...

    java线程实例 各种小Demo

    - interrupt():中断线程,被中断的线程会抛出InterruptedException。 - isInterrupted() 和 interrupted():检查线程是否被中断。 三、线程同步 为了解决多线程并发访问共享资源可能导致的问题,Java提供了多种...

    Java工程师线程试题

    7. **线程中断**:`interrupt()`方法用于中断线程,中断标志会被设置。线程内部可以通过检查`isInterrupted()`或`interrupted()`来响应中断请求,通常用于终止阻塞操作如`sleep()`或`wait()`。 8. **线程生命周期**...

    线程的各种使用方式Demo

    - `Thread.interrupt()`:标记线程中断状态,通常配合`isInterrupted()`或`interrupted()`检查中断状态,并在适当位置结束线程。 - `InterruptedException`:当线程在阻塞状态下被中断时抛出,需妥善处理。 8. **...

    java多线程中断代码详解

    Java 提供了多种方式来中断线程,包括使用 stop() 方法、interrupt() 方法和使用 volatile 变量等。 一、Java 中断线程的方式 Java 中有三种方式来中断线程: 1. 使用 stop() 方法:该方法已经被废弃,因为它可能...

    java多线程测试实例

    - `interrupt()`方法用于中断线程,但这并不意味着线程会立即停止,而是设置中断标志,线程需在适当位置检查`isInterrupted()`或`interrupted()`方法来响应中断。 - 守护线程(Daemon Thread)是一种后台线程,当...

    Android中断并重启一个Thread线程的简单方法

    因此,中断线程后,若需要重新启动,必须创建一个新的`Thread`实例: ```java public void restartThread() { mThread = new MyThread(); mThread.start(); } ``` 在Android开发中,通常推荐使用`Handler`、`...

Global site tag (gtag.js) - Google Analytics