PS:本文中的thread一词的大小写没打错,thread是线程对象,Thread是调用静态方法

中断相关方法介绍

  • thread.interrupt() 方法会设置线程的状态为”中断”;
  • Thread.interrupted()thread.isInterrupted() 两个方法用于判断当前线程的状态是否为”中断”:

Thread.interrupted() == Thread.currentThread().isInterrupted(true)
thread.isInterrupted() == thread.isInterrupted(false)

  • isInterrupted()的源码是:
    1. private native boolean isInterrupted(boolean ClearInterrupted);
    这是一个native方法,但我们还是能知道isInterrupted()的boolean参数是用于是否重置”中断状态”。

如前所述interrupt()方法不会直接中断线程,而只是把线程的状态设置为”中断”。
我们常用的Thread.sleep()、thread.wait()、thread.join()等方法时总是会要求我们处理InterruptedException异常 ,实质上就是因为这几个方法会监视线程状态,如果发现状态为”中断”,就会抛出该异常。

如果我们要主动中断线程的执行,要在线程外部调用thread.interrupt()发送中断信号,并且在线程内部监视当前线程的中断状态,主动处理中断。如果我们线程内部什么都不做,thread.interrupt() 就仅仅是白给。
Example1

  1. public class Main {
  2. public static void main() {
  3. Thread t = new MyThread();
  4. t.start();
  5. Thread.sleep(1000);
  6. t.interrupt();
  7. }
  8. }
  9. class MyThread extends Thread {
  10. @Override
  11. public void run() {
  12. int i = 0;
  13. while(!Thread.interrupted()) {
  14. // ......
  15. i++;
  16. }
  17. System.out.println(i); // 1380101433
  18. }
  19. }

中断使用场景

服务器日常执行数据处理任务,这些任务会占用大量CPU、内存资源。
当在计算高峰期上中途插入加急任务,加急任务要如何获取足够的资源去计算?

这里我提供两种方法。

  1. 是在每次线程启动前时设置线程优先级:thread.setPriority(int priority)

日常的任务直接使用默认值,加急任务则设置Thread.MAX_PRIORITY

  1. 终止其它线程的执行,释放资源。

根据线程的实现方式,可以使用thread.interrupt() 或是 future.cancel()等方式发送中断信号,线程收到信号后主动暂停任务释放资源。

方法1适用于纯Java处理数据、不要求线程间执行顺序的情况。纯Java程序会由JVM调配CPU资源,通过设置优先级的方式尽可能分配多的CPU资源。
方法2适用于通过Java调用其他语言的插件/脚本的情况。一般来说,这时我们使用的是Process相关的API执行系统command。process.start()会生成新的进程,而进程无法继承线程优先级的。线程收到中断信号后通过杀掉进程树的方式释放资源,杀完进程树之后线程就执行完毕了(当然这不是正常执行完)。