不安全的中断方式:循环中设置标志位flag
public static class FalgCancelDemo implements Runnable{
private volatile boolean flag=true;
@Override
public void run() {
while(flag){
//domywork (自己的业务逻辑)
Thread.sleep(10000);
}
}
//中断方法
public void cancel(){
flag=false;
}
}
中断线程的时候如果我的业务逻辑是个阻塞的逻辑,那么设置flag是不能立马中断线程的,线程仍然会等sleep结束或者自己的业务逻辑执行结束才能中断,这就造成用户要求中断,但中断之后仍然没有中断的尴尬局面。
解决方法:循环中设置标志位flag,同时加入interupted判断
public static class InteruputCancelDemo implements Runnable{
private volatile boolean flag=true;
@Override
public void run() {
while (flag && !Thread.currentThread().isInterrupted()){
try {
Thread.sleep(100);//这种阻塞方法会一直检查当前线程的标志位
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
e.printStackTrace();
}
}
}
//中断方法
public void cancel(Thread toInteruptThread){
flag=false;
toInteruptThread.interrupt();//设置要中断线程标志位为false
}
}
注意点:程序捕获异常之后会隐含调用Thread.interrputed()方法,将中断标志位会改成false
聪明的你可能看到在捕获异常的时候加了一句Thread.currentThread().interrupt();
这里也是大有学问。当然在这段代码中是并没有实质性的效果的。下面再看一段代码
public static class InteruptDemo implements Runnable{
private Object lock=new Object();
private int i;
@Override
public void run() {
while(!Thread.currentThread().isInterrupted()){
try{
synchronized (lock){
lock.wait();
System.out.println(i++);
}
}catch (InterruptedException e){
System.out.println("当前线程的标志位:"+Thread.currentThread().isInterrupted());
Thread.currentThread().interrupt();
System.out.println("当前线程的标志位:"+Thread.currentThread().isInterrupted());
}
}
}
public void cancle(Thread thread){
thread.interrupt();
}
下面是main方法:
public static void main(String[] args) throws InterruptedException {
InteruptDemo interuptDemo=new InteruptDemo();
Thread test=new Thread(interuptDemo);
test.start();
Thread.sleep(10);
interuptDemo.cancle(test);
}
程序输出:
当前线程的标志位:false
当前线程的标志位:true
诸如wait(),sleep()等会抛出中断异常的方法,在程序执行的过程中都会去检查当前线程的中断标志位,如果标志位为true就会抛出中断异常,但是在抛出异常后,中断标志位会改成自动复位为false,可以理解为这些方法会隐含调用Thread.interrputed()方法。所以说如果我们在捕获异常之后不加Thread.currentThread().interrupt();
就会导致程序仍然不能正常结束。
网友评论