Java中的线程中断

时间:2020-01-09 10:35:07  来源:igfitidea点击:

线程中断表示线程应停止执行当前正在执行的操作,然后终止或者执行其他操作。线程被中断后的工作由我们自己决定,但是约定是线程一旦中断应终止。

Java中的线程中断如何工作

在Java Thread类中,有一个方法interrupt()中断调用线程。线程中断后,其中断状态将设置为true,然后根据线程当前是否被阻塞而进行后续活动

  • 如果在调用Object类的wait(),wait(long)或者wait(long,int)方法或者join(),join(long),join(long,int)方法时阻塞了此线程,sleep(long)或者sleep(long,int)此类的方法,则其中断状态将被清除(再次设置为false),并且将收到InterruptedException。
  • 如果此线程在InterruptibleChannel上的I / O操作中被阻止,则该通道将被关闭,该线程的中断状态将被设置,并且该线程将收到ClosedByInterruptException。
  • 如果此线程在选择器中被阻塞,则该线程的中断状态将被设置,并且它将立即从选择操作中返回,可能具有非零值,就像调用选择器的唤醒方法一样。
  • 如果未阻塞的线程被中断,则将设置该线程的中断状态。

与Java Thread类中的线程中断有关的方法

除了上面已经讨论的方法interrupt()之外,java.lang.Thread类中还有两个与线程中断interrupted()和isInterrupted()相关的方法。

  • void interrupt()–中断此线程。
  • static boolean interrupted()–检查当前线程是否已被中断。同时清除线程的中断状态。
  • boolean isInterrupted()–测试此线程是否已被中断。此方法不会以任何方式更改线程的中断状态。

线程中断的例子

Java中的线程中断通常用于终止阻塞线程。因此,我们可以选择在中断睡眠或者等待线程后仅返回。

public class InterruptDemo implements Runnable {
	
  @Override
  public void run() {
    for(int i = 0; i < 5; i++){
      System.out.println("Value - " + i);
      try {
        Thread.sleep(500);
      } catch (InterruptedException e) {
        System.out.println("Thread " + Thread.currentThread().getName() + " interrupted, reason " + e.getMessage());
        System.out.println("Interrupted status- " + Thread.currentThread().isInterrupted());
        return;
      }
    }	
  }

  public static void main(String[] args) {
    Thread t = new Thread(new InterruptDemo());
    t.start();
    t.interrupt();
    System.out.println("In main method - Interrupted status " + t.isInterrupted());
  }
}

输出:

In main method - Interrupted status true
Value - 0
Thread Thread-0 interrupted, reason sleep interrupted
Interrupted status- false

在线程的run方法中,有一个循环来打印从1到5的数字,每次显示数字后,都会在线程上调用sleep方法。同时,也会调用线程的中断方法,以中断被阻塞的线程。我们还可以看到在调用interrupt()方法之后,中断状态为true,然后清除了中断状态(设置为false)。

包装并重新抛出InterruptedException

我们可以选择包装InterruptedException并将其重新抛出,而不是像前面的示例中那样返回。

public class InterruptDemo implements Runnable {
  @Override
  public void run() {
    for(int i = 0; i < 5; i++){
      System.out.println("Value - " + i);
      try {
        Thread.sleep(500);
      } catch (InterruptedException e) {
        System.out.println("Thread " + Thread.currentThread().getName() + " interrupted, reason " + e.getMessage());
        System.out.println("Interrupted status- " + Thread.currentThread().isInterrupted());
        throw new RuntimeException("Thread interrupted", e);
      }
    }	
  }

  public static void main(String[] args) {
    Thread t = new Thread(new InterruptDemo());
    t.start();
    t.interrupt();
    System.out.println("In main method - Interrupted status " + t.isInterrupted());
  }
}

输出:

In main method - Interrupted status true
Value - 0
Thread Thread-0 interrupted, reason sleep interrupted
Interrupted status- false
Exception in thread "Thread-0" java.lang.RuntimeException: Thread interrupted
	at com.theitroad.InterruptDemo.run(InterruptDemo.java:14)
	at java.lang.Thread.run(Unknown Source)
Caused by: java.lang.InterruptedException: sleep interrupted
	at java.lang.Thread.sleep(Native Method)
	at com.theitroad.InterruptDemo.run(InterruptDemo.java:10)
	... 1 more

中断非阻塞线程

如果中断未阻塞的线程,则仅线程的中断状态会更改。使用isInterrupted()方法,我们可以检查线程的中断状态,并选择在该条件下执行一些逻辑。

public class InterruptDemo implements Runnable {
  @Override
  public void run() {
    for(int i = 0; i < 5; i++){
      System.out.println("Value - " + i);
      if(Thread.currentThread().isInterrupted()){
        System.out.println("Interrupted status- " + Thread.currentThread().isInterrupted());
      }
    }	
  }

  public static void main(String[] args) {
    Thread t = new Thread(new InterruptDemo());
    t.start();
    t.interrupt();
    System.out.println("In main method - Interrupted status " + t.isInterrupted());
  }
}

输出:

In main method - Interrupted status true
Value - 0
Interrupted status- true
Value - 1
Interrupted status- true
Value - 2
Interrupted status- true
Value - 3
Interrupted status- true
Value - 4
Interrupted status- true

如我们所见,在这种情况下,中断状态保持为true,不会像被中断的阻塞线程一样清除为false。