java Thread interrupt()

Java 线程之中,一个线程的生命周期分为:初始、就绪、运行、阻塞以及结束。当然,其中也可以有四种状态,初始、就绪、运行以及结束。

一般而言,可能有三种原因引起阻塞:等待阻塞、同步阻塞以及其他阻塞(睡眠、join或者IO阻塞);

对于Java而言,

  • 等待阻塞是调用 wait() 产生的,
  • 同步阻塞则是由同步块(synchronized)产生的,
  • 睡眠阻塞是由 sleep() 产生的,
  • join阻塞是由 join() 产生的。

言归正传,要中断一个Java线程,可调用线程类的 interrupt() 方法;然而 interrupt() 方法并不会立即执行中断操作;具体而言,这个方法只会给线程设置一个为 true 的中断标志(中断标志只是一个布尔类型的变量),而设置之后,则根据线程当前的状态进行不同的后续操作。

如果,线程的当前状态处于非阻塞状态,那么仅仅是线程的中断标志被修改为true而已;

如果线程的当前状态处于阻塞状态,那么在将中断标志设置为true后,还会有如下三种情况之一的操作:

  • 如果是wait、sleep以及jion三个方法引起的阻塞,那么会将线程的中断标志 重新设置为 false,并抛出一个InterruptedException;
  • 如果是java.nio.channels.InterruptibleChannel进行的io操作引起的阻塞,则会对线程抛出一个ClosedByInterruptedException;(待验证)
  • 如果是轮询(java.nio.channels.Selectors)引起的线程阻塞,则立即返回,不会抛出异常。(待验证)

如果在中断时,线程正处于非阻塞状态,则将中断标志修改为true,而在此基础上,一旦进入阻塞状态,则按照阻塞状态的情况来进行处理。例如,一个线程在运行状态中,其中断标志被设置为true,则此后,一旦线程调用了wait、jion、sleep方法中的一种,立马抛出一个InterruptedException,且中断标志被清除,重新设置为false。

总结,调用线程类的interrupted() 方法,其本质只是设置该线程的中断标志,将中断标志设置为true,并根据线程状态决定是否抛出异常。因此,通过interrupted方法真正实现线程的中断原理是:开发人员根据中断标志的具体值,来决定如何退出线程。

一个简单的实现方式如下:

public void run() {  
    try {  
        while (true){  
            Thread.sleep(1000l);//阻塞状态,线程被调用了interrupte()方法,清除中断标志,抛出InterruptedException  
            
            //dosomething  
            boolean isIn = this.isInterrupted();  
            
            //运行状态,线程被调用了interrupte()方法,中断标志被设置为true  
            //非阻塞状态中进行中断线程操作  
            if(isIn) 
            	break;//退出循环,中断进程  
        }  
    }catch (InterruptedException e){//阻塞状态中进行中断线程操作  
        boolean isIn = this.isInterrupted();//退出阻塞状态,且中断标志被清除,重新设置为false,所以此处的isIn为false  
        return;//退出run方法,中断进程  
    }  
}  

分别考虑了阻塞状态中进行中断线程和非阻塞状态中中断线程的处理方式。

最后,说明一下interrupte()方法的调用,该方法可在需要中断的线程本身中调用,也可在其他线程中调用需要中断的线程对象的该方法。

代码示例:

package com.aop8.thread1;

public class InterruptDemo {  
    public static void main(String[] args) throws Exception {  
        Thread t = new Thread(new Worker());  
        t.start();  
          
        Thread.sleep(200);  
        t.interrupt();  
          
        System.out.println("Main thread stopped.");  
    }  
      
    public static class Worker implements Runnable {  
        public void run() {  
            System.out.println("Worker started.");  
              
            try {  
                Thread.sleep(50000);  
            } catch (InterruptedException e) {  
                System.out.println("Worker IsInterrupted: " +   
                        Thread.currentThread().isInterrupted());  
            }  
              
            System.out.println("Worker stopped.");  
        }  
    }  
}  

代码说明:

主线程main启动了一个子线程Worker,然后让worker睡500ms,而main睡200ms,之后main调用worker线程的interrupt方法去中断worker,worker被中断后打印中断的状态。

运行结果:

Worker started.
Main thread stopped.
Worker IsInterrupted: false
Worker stopped.

Worker IsInterrupted: false 为什么是false,而不是true ? 参考文章: https://blog.csdn.net/hj7jay/article/details/53462553

转载:http://www.cnblogs.com/w-wfy/p/6415005.html
参考文章: https://www.cnblogs.com/w-wfy/p/6414801.html

猜你喜欢

转载自blog.csdn.net/xiaojin21cen/article/details/89885472