Interrupt相关方法
在Java中调用interrupt方法可以中断进程。与之相关的方法有
isInterrupted()
:返回一个boolean值,用于判断当前现成的打断状态。此方法不会重置打断标记。interrupted()
:返回一个boolean值,用于判断当前现成的打断状态。此方法会重置打断标记。
Interrupt中断标记
需要注意的是,当调用interrupt方法大打断的时处于sleep、wait、join的方法时,会触发打断异常,但是打断标记会重置为false。示例程序如下:
import lombok.extern.slf4j.Slf4j;
import java.util.concurrent.locks.LockSupport;
@Slf4j
public class Test1_Interrupt {
static final Object lock = new Object();
public static void main(String[] args) {
Thread t1 = new Thread(() -> {
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
Thread current = Thread.currentThread();
log.debug(String.valueOf(current.isInterrupted()));
}
}, "t1");
Thread t2 = new Thread(() -> {
synchronized (lock){
try {
lock.wait();
} catch (InterruptedException e) {
Thread current = Thread.currentThread();
log.debug(String.valueOf(current.isInterrupted()));
}
}
}, "t2");
Thread t3 = new Thread(() -> {
while (true){
Thread current = Thread.currentThread();
if(current.isInterrupted()){
log.debug(String.valueOf(current.isInterrupted()));
return;
}
}
}, "t3");
Thread t4 = new Thread(() -> {
try {
t3.join();
} catch (InterruptedException e) {
Thread current = Thread.currentThread();
log.debug(String.valueOf(current.isInterrupted()));
}
}, "t4");
Thread t5 = new Thread(() -> {
log.debug("park...");
LockSupport.park();
LockSupport.park();
LockSupport.park();
log.debug("unpark...");
log.debug("打断状态:{}", Thread.currentThread().isInterrupted());
}, "t5");
t1.start();
t2.start();
t3.start();
t4.start();
t5.start();
t1.interrupt();
t2.interrupt();
t4.interrupt();
t3.interrupt();
t5.interrupt();
}
}
上述程序构建了四个线程:
- t1:调用了sleep方法
- t2:调用了wait方法
- t3:正常运行的线程
- t4:调用了join方法,等待线程t3结束
- t5:调用了park、unpark方法
输出如下
19:46:57.597 [t5] DEBUG chapter3.Test1_Interrupt - park...
19:46:57.597 [t1] DEBUG chapter3.Test1_Interrupt - false
19:46:57.597 [t4] DEBUG chapter3.Test1_Interrupt - false
19:46:57.603 [t5] DEBUG chapter3.Test1_Interrupt - unpark...
19:46:57.597 [t2] DEBUG chapter3.Test1_Interrupt - false
19:46:57.597 [t3] DEBUG chapter3.Test1_Interrupt - true
19:46:57.603 [t5] DEBUG chapter3.Test1_Interrupt - 打断状态:true
可以看到,只有正常运行的线程被打断是,park方法打断即失效,其余放啊被打断,打断标记才是true。
模式之两阶段终止
目的:为了在线程被打断后能够正确的释放资源。
方法:启动监视线程,每隔一段时间判断令一线程的中断状态,若发现被打断,则启动清理程序。
流程图如下:
对应代码如下:
import lombok.extern.slf4j.Slf4j;
@Slf4j
public class Test2_TwoStageStop {
public static void main(String[] args) {
TPTInterrupt tpt = new TPTInterrupt();
tpt.start();
try {
// Thread.sleep(200);
Thread.sleep(2000);
tpt.stop();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
@Slf4j
class TPTInterrupt{
private Thread thread;
public void start(){
thread = new Thread(() -> {
while(true){
Thread current = Thread.currentThread();
if(current.isInterrupted()){
log.debug("正常中断");
clear();
return;
}
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
log.debug("睡眠时被打断");
log.debug(String.valueOf(current.isInterrupted()));
current.interrupt();
}
}
}, "监控线程");
thread.start();
}
public void stop(){
thread.interrupt();
}
public void clear(){
log.debug("料理后事");
}
}
当监视线程在睡眠过程中被打断后,需要重置打断标记(因为在睡眠过程中被打断,中断标记字会被清空)。