PS:本文中的thread一词的大小写没打错,thread是线程对象,Thread是调用静态方法
中断相关方法介绍
thread.interrupt()
方法会设置线程的状态为”中断”;Thread.interrupted()
和thread.isInterrupted()
两个方法用于判断当前线程的状态是否为”中断”:
Thread.interrupted() == Thread.currentThread().isInterrupted(true)
thread.isInterrupted() == thread.isInterrupted(false)
- 而
isInterrupted()
的源码是:
这是一个native方法,但我们还是能知道private native boolean isInterrupted(boolean ClearInterrupted);
isInterrupted()
的boolean参数是用于是否重置”中断状态”。
如前所述interrupt()
方法不会直接中断线程,而只是把线程的状态设置为”中断”。
我们常用的Thread.sleep()、thread.wait()、thread.join()等方法时总是会要求我们处理InterruptedException异常
,实质上就是因为这几个方法会监视线程状态,如果发现状态为”中断”,就会抛出该异常。
如果我们要主动中断线程的执行,要在线程外部调用thread.interrupt()
发送中断信号,并且在线程内部监视当前线程的中断状态,主动处理中断。如果我们线程内部什么都不做,thread.interrupt()
就仅仅是白给。
Example1
public class Main {
public static void main() {
Thread t = new MyThread();
t.start();
Thread.sleep(1000);
t.interrupt();
}
}
class MyThread extends Thread {
@Override
public void run() {
int i = 0;
while(!Thread.interrupted()) {
// ......
i++;
}
System.out.println(i); // 1380101433
}
}
中断使用场景
服务器日常执行数据处理任务,这些任务会占用大量CPU、内存资源。
当在计算高峰期上中途插入加急任务,加急任务要如何获取足够的资源去计算?
这里我提供两种方法。
- 是在每次线程启动前时设置线程优先级:
thread.setPriority(int priority)
;
日常的任务直接使用默认值,加急任务则设置Thread.MAX_PRIORITY
。
- 终止其它线程的执行,释放资源。
根据线程的实现方式,可以使用thread.interrupt()
或是 future.cancel()
等方式发送中断信号,线程收到信号后主动暂停任务释放资源。
方法1适用于纯Java处理数据、不要求线程间执行顺序的情况。纯Java程序会由JVM调配CPU资源,通过设置优先级的方式尽可能分配多的CPU资源。
方法2适用于通过Java调用其他语言的插件/脚本的情况。一般来说,这时我们使用的是Process相关的API执行系统command。process.start()会生成新的进程,而进程无法继承线程优先级的。线程收到中断信号后通过杀掉进程树的方式释放资源,杀完进程树之后线程就执行完毕了(当然这不是正常执行完)。