Java多线程学习之Interrupt中断

引言

本文将由以下几点来说明Interrupt中断:
1.什么是中断?为什么使用中断?
2.中断的作用
3.中断的使用

1.什么是中断Interrupt?

  一般来说,当线程在执行完run方法的最后一句话或者在执行过程中出现没有捕获的异常的话,这个线程就被终止了。这两种线程终止方式都是非人为控制的终止,如果开发人员希望可以人为可控地手动终止一个线程来取消该线程中进行IO下载、取消上传等操作,该如何解决呢?

中断与stop方法

  在Java早期版本中,有一个stop方法,其他线程可以调用该方法终止某一个线程,但已经被弃用了,原因是stop方法会终止所有未结束的方法,包括run方法,当线程被终止时,立即释放被它锁住的所有对象的锁。这会导致线程不安全。举个栗子:假设线程A在从一个账户向另一个账户转账的过程中被终止,钱已经打出去了,但是另一个账户却还没来得及接收钱。而开发者是无法知道什么时候调用stop方法是安全的,因此该方法被弃用。
  中断与stop不同,interrupt中断其实是每个线程的一个boolean状态,该状态本身并不能发挥任何作用,需要开发人员进行处理。简单来说,我们在某一个线程中使用中断方法来将目标线程设置为中断状态(Thread.currentThread().intertupe()),并不会终止该目标线程,只是告诉该线程有人需要你终止,如果在该线程中没有进行检测中断状态来自行处理,那么设置该线程的中断状态是没有任何作用的!

2.中断的作用

  中断的第一个作用已经呼之欲出了,作用一:让线程可以结合业务场景灵活地处理自身的中断状态,如可控地终止线程!下面看看如何使用中断来终止一个线程:

 public static void main(String[] args) throws InterruptedException {
        Thread thread = new Thread(new InterruptedRunnable());
        thread.start();
        Thread.sleep(1000);
        thread.interrupt();
    }

    static class InterruptedRunnable implements  Runnable{
        @Override
        public void run() {
            while (true){
                System.out.println("thread is ruuning!");
                if (Thread.currentThread().isInterrupted()){
                    //如果被设置为中断了
                    System.out.println("我被中断了!");
                    break;
                }
            }
        }
    }

  在thread线程中循环执行打印thread is runnning!,并检测自身中断状态,如果被其他线程中断了就退出循环,终止线程,主线程一秒后置位该线程中断状态(即设置为1/true),该线程成功终止!
作用二:中断线程的等待
  当线程进入等待状态时(即TIMED_WAITING,WAITING状态:通过调用Thread#join()方法或者Object#wait()方法(不设置超时时间,with no timeout)或者LockSupport#park()方法可以让一个线程从RUNNABLE状态转为WAITING状态;TIMED_WAITING指线程处于等待中,但是这个等待是有期限的(),通过调用Thread#sleep(),Object#wait(long timeout),Thread#join(long timeout),进入TIMED_WAITING状态)上调用interrupt方法来置位中断状态时,阻塞调用将会被Interrupted Exception异常中断,清除该线程的阻塞状态!从另一个角度来说,当某一个方法提示你有需要捕获Interrupted Exception时就暗示该方法是可以被另一个线程通过interrupt方法中断清除当前状态的,如:BlockingQueue#put、BlockingQueue#take、Object#wait、Thread#sleep等。

Interrupted Exception异常的处理

一般有以下两个通用原则:
 1.如果遇到的是可中断的阻塞方法抛出InterruptedException,可以继续向方法调用栈的上层抛出该异常,如果是检测到中断,则可清除中断状态并抛出InterruptedException,使当前方法也成为一个可中断的方法。
 2.若有时候不太方便在方法上抛出InterruptedException,比如要实现的某个接口中的方法签名上没有throws InterruptedException,这时就可以捕获可中断方法的InterruptedException并通过Thread.currentThread.interrupt()来重新设置中断状态。如果是检测并清除了中断状态,亦是如此

3.中断的使用

java.lang.Thread类提供了几个方法来操作这个中断状态,这些方法包括:
1.public static boolean interrupted
 测试当前线程是否已经中断。线程的中断状态 由该方法清除。换句话说,如果连续两次调用该方法,则第二次调用将返回 false(在第一次调用已清除了其中断状态之后,且第二次调用检验完中断状态前,当前线程再次中断的情况除外)。
2.public boolean isInterrupted()
 测试线程是否已经中断。线程的中断状态不受该方法的影响。
3.public void interrupt()
 中断线程

中断的几个使用场景

1.点击某个桌面应用中的取消按钮时;
2.某个操作超过了一定的执行时间限制需要中止时;
3.多个线程做相同的事情,只要一个线程成功其它线程都可以取消时;
4.一组线程中的一个或多个出现错误导致整组都无法继续时;
5.当一个应用或服务需要停止时。

参考:

  • https://www.cnblogs.com/jiangzhaowei/p/7209949.html
  • https://www.jianshu.com/p/678e17386e79
  • 《Java核心技术》

你可能感兴趣的:(Java多线程学习之Interrupt中断)