java并发总结3(中断线程)

Java线程中断机制详解
本文深入探讨Java中线程的中断机制,包括线程的基本状态、如何使用interrupt()方法中断线程及其实际效果,并提供了具体的代码示例。

我们先来了解下线程的几种状态:

  1. 新建状态(New):一个新的线程在被创建之后,在运行(或阻塞)之前的状态。

  2. 就绪状态(Runnable):当一个线程只要拥有CPU时间片就能运行的时候,这个线程就处于就绪状态。

  3. 阻塞状态(Blocked):线程还没有死亡,但是由于一些原因不能继续运行,但是还能回到就绪状态。

  4. 死亡状态(Dead):当一个线程的任务已经完成,即run方法已经正确返回,或者被中断,这个线程就处于死亡状态。

线程阻塞的原因
  • 调用了Thread.sleep()方法;

  • 调用了wait(),线程被挂起;

  • 线程在等待其他操作完成。例如正在等待输入;

  • 线程在等待其他线程持有的锁。

    线程中断

    java Thread中通过interrupt()方法中断线程,文档中对这个方法的功能描述是:

 Interrupts this thread.
  • 但是,这个方法并不能轻而易举地中断一个线程。我们可以用下面的代码进行测试:

  •  

  • public class InterruptThread extends Thread {
    
     @Override
    
     public void run() {
    
      while(true){
    
       System.out.println("执行中...");
    
      }
    
     }
    
     
    
     public static void main(String[] args) {
    
      InterruptThread interruptThread = new InterruptThread();
    
      interruptThread.start();
    
      interruptThread.interrupt();
    
     }
    
    }
  • InterruptThread继承了Thread,在执行中即使调用了interrupt()方法。控制台还是不断地在打印。

  • 看来,interrupt()方法并没有成功的中断我们的线程。

    其实可以这样来类比(注意,只是类比,实际情况并不完全是这样):Thread类中有一个boolean的标志域用来表示线程是否需要被中断,默认是false。interrupt()方法被调用之后,这个标志域就变成了true。当然,Thread类有一个interrupted()方法返回一个boolean值,返回的就是这个标志域的值。也就是说,其实interrupt()方法除了把这个标志域设定为true之后,其他什么也没干了。这就解释了上例中的线程为什么不能被正确地中断。所以,我们可以把SimpleThread类的run()方法改写成下面这个样子:

  •  

  • public class InterruptThread extends Thread {
    
     @Override
    
     public void run() {
    
      while(!interrupted()){
    
       System.out.println("执行中...");
    
      }
    
     }
    
     
    
     public static void main(String[] args) {
    
      InterruptThread interruptThread = new InterruptThread();
    
      interruptThread.start();
    
      try {
    
       Thread.sleep(1000);//cpu执行过快,interrupThread还来不及运行就被interrupt()了,所以让主线程休眠1s
    
      } catch (InterruptedException e) {
    
       e.printStackTrace();
    
      }
    
      interruptThread.interrupt();
    
     }
    
    }
  • 再运行测试程序,就会发现,1秒后线程会停止打印,它确实是被中断了。

  • 有时候,我们不仅仅想要中断一个像上面这样重复着做同一件事的线程。很多情况下,我们需要的是中断一个休眠中的线程。毕竟开始因为某种需要,让一个线程休眠一段很长的时间,后来你就后悔了,想中断它的休眠。这个时候,interrupt()方法就又有用武之地了。

    比如:

  •  

  • public class InterruptThread extends Thread {
    
     @Override
    
     public void run() {
    
      System.out.println("I want to sleep, Do not bother me!");
    
      try {
    
       Thread.sleep(2000);
    
      } catch (InterruptedException e) {
    
    //   e.printStackTrace();
    
       System.out.println("my god, somebody bothered me.");
    
      }
    
      System.out.println("Wake up!");
    
     }
    
     
    
     public static void main(String[] args) {
    
      InterruptThread interruptThread = new InterruptThread();
    
      interruptThread.start();
    
    //  interruptThread.interrupt();
    
     }
    
    }
  • I want to sleep, Do not bother me!
    Wake up!
  •  

  • 如果我们放开
    //  interruptThread.interrupt();的注释

  • public class InterruptThread extends Thread {
    
     @Override
    
     public void run() {
    
      System.out.println("I want to sleep, Do not bother me!");
    
      try {
    
       Thread.sleep(2000);
    
      } catch (InterruptedException e) {
    
    //   e.printStackTrace();
    
       System.out.println("my god, somebody bothered me.");
    
      }
    
      System.out.println("Wake up!");
    
     }
    
     
    
     public static void main(String[] args) {
    
      InterruptThread interruptThread = new InterruptThread();
    
      interruptThread.start();
    
      interruptThread.interrupt(); 
    
     }
    
    }
  • I want to sleep, Do not bother me!
    my god, somebody bothered me.
    Wake up!
  • 一个人睡觉,不能保证不被打搅;同理,一个线程在休眠,不能保证不被中断。这就是为什么Thread的sleep()方法会可能抛出一个InterruptedException的原因。同样地,Thread类的join()方法,Object类的wait()方法,都可能抛出InterruptedException。

    所以,如果想要中断一个正在sleep或者join或者wait的线程,调用线程的interrupt()方法即可,然后把在中断后需要的操作写进catch语句块里。

转载于:https://my.oschina.net/modi/blog/228399

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值