java中所有的中断,并不能真正结束和中断线程,下图中的running状态和同步锁状态的线程,中断只是改变了它们的中断标识,并没有中断线程。
官方文档解释:
1. 如果该线程阻塞的调用wait(),wait(long)或wait(long, int)该方法的Object 类,或的join(),join(long),join(long, int),sleep(long),或者sleep(long, int),这个类的方法,那么它的中断状态将被清除,它还将收到一个InterruptedException。
2. 如果此线程在I / O操作中被阻塞,InterruptibleChannel 则通道将被关闭,线程的中断状态将被设置,并且线程将接收到ClosedByInterruptException。
3. 如果此线程被阻塞,Selector 则线程的中断状态将被设置,并且它将从选择操作立即返回,可能具有非零值,就像wakeup调用了选择器的方法一样。(非阻塞式IO)
4. 如果以前的条件都不成立,则该线程的中断状态将被设置。
5. 中断不存在的线程不需要任何效果。
测试代码:
import org.junit.Test;
public class TestInterrupt {
/**
* 调用wait(),wait(long)或wait(long, int),
* 或的join(),join(long),join(long, int),
* sleep(long),sleep(long, int),
* 那么它的中断状态将被清除,它还将收到一个InterruptedException
*/
@Test
public void testSleep(){
Thread sleep = new Thread(msgRunnable(()->{
try {
Thread.sleep(100);
// synchronized (this) {
// wait(100);
// }
} catch (InterruptedException e) {
e.printStackTrace();
}
}),"sleep线程");
sleep.start();
interrupt(sleep);
}
volatile boolean flag = true;
/**
* 无法中断没有阻塞的线程
*/
@Test
public void testRunningJob(){
Thread running = new Thread(msgRunnable(()->{while(flag) System.out.println("running");}),"running线程");
running.start();
interrupt(running);
try {
Thread.sleep(1);
} catch (InterruptedException e) {
e.printStackTrace();
}
flag = false;
}
/**
* 无法中断由同步锁阻塞的线程
* @throws InterruptedException
*/
@Test
public void testSynchronized() throws InterruptedException{
Object o = new Object(){
@Override
public synchronized String toString() {
return "object";
}
@Override
public synchronized int hashCode() {
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
return super.hashCode();
}
};
//线程A先调用o的hashCode方法,对o进行加锁
//线程synch调用o的toString方法,同步锁阻塞
//主线程企图中断synch
//结果当然是主线程并不能中断synch线程,只是改变了synch的中断标识
Thread A = new Thread(o::hashCode);
A.start();
//暂停1毫秒保证A执行在synch前,对o进行加锁
Thread.sleep(1);
Thread synch = new Thread(msgRunnable(o::toString),"synch线程");
synch.start();
long start = System.currentTimeMillis();
interrupt(synch);
//等待synch执行完毕
synch.join();
System.out.println("synch线程中断后持续的执行时间:"+(System.currentTimeMillis()-start));
}
/**
* 等待30纳秒,中断线程
* @param thread
*/
private void interrupt(Thread thread) {
try {
Thread.sleep(0,30);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName()+":正在中断wait");
thread.interrupt();
}
public Runnable msgRunnable(final Runnable r){
return ()->{
System.out.println(Thread.currentThread().getName()+"正在执行");
r.run();
System.out.println(Thread.currentThread().getName()+"中断状态为:"+Thread.currentThread().isInterrupted());
System.out.println(Thread.currentThread().getName()+"结束");
};
}
}