线程中断意思
中断的意思,即给线程附上一个中断的标记,是标记,给个标记只是表明请求终止这个线程,并不是立马就给终止了,具体终止还得靠线程自己。
线程标记
关于线程标记,调用某个线程的interrupt方法,即t.interrupt(),就会给当前打上中断标记。
关于线程中断标记的消除:
-
Thread.interrupted() 静态方法:该方法会判断当前线程是不是被中断标记了,同时会清除该线程的中断标记,这点很重要。
-
遇上interruptedException:被catch到了,执行里面的代码,并且中断标记会清除。
-
t.isInterrupted():判断t是不是被中断标记了,这个并不会清除中断标记。
一个例子:
public class InterruptSignIsClean {
public static void main(String[] args) {
Thread carOne = new Thread(() -> {
long startMills = System.currentTimeMillis();
while (System.currentTimeMillis() - startMills < 3) {
//if (Thread.currentThread().isInterrupted()) {
if (Thread.interrupted()) {
SmallTool.printTimeAndThread("被中断了还开个毛???");
} else {
SmallTool.printTimeAndThread("没被中断继续开");
}
}
});
carOne.start();
SmallTool.sleepMillis(1);
carOne.interrupt();
/**
* 运行结果:
* (调用Thread.currentThread().isInterrupted())
* 1641827127303 | 11 | Thread-0 | 没被中断继续开
1641827127303 | 11 | Thread-0 | 被中断了还开个毛???
1641827127304 | 11 | Thread-0 | 被中断了还开个毛???
1641827127304 | 11 | Thread-0 | 被中断了还开个毛???
1641827127304 | 11 | Thread-0 | 被中断了还开个毛???
1641827127304 | 11 | Thread-0 | 被中断了还开个毛???
1641827127304 | 11 | Thread-0 | 被中断了还开个毛???
1641827127304 | 11 | Thread-0 | 被中断了还开个毛???
1641827127304 | 11 | Thread-0 | 被中断了还开个毛???
1641827127304 | 11 | Thread-0 | 被中断了还开个毛???
1641827127304 | 11 | Thread-0 | 被中断了还开个毛???
1641827127304 | 11 | Thread-0 | 被中断了还开个毛???
1641827127304 | 11 | Thread-0 | 被中断了还开个毛???
1641827127305 | 11 | Thread-0 | 被中断了还开个毛???
*
*
* 调用Thread.interrupted()这个静态方法,会清楚中断标志位
1641827423247 | 11 | Thread-0 | 没被中断继续开
1641827423247 | 11 | Thread-0 | 没被中断继续开
1641827423247 | 11 | Thread-0 | 没被中断继续开
1641827423248 | 11 | Thread-0 | 没被中断继续开
1641827423248 | 11 | Thread-0 | 被中断了还开个毛???
1641827423248 | 11 | Thread-0 | 没被中断继续开
1641827423248 | 11 | Thread-0 | 没被中断继续开
1641827423248 | 11 | Thread-0 | 没被中断继续开
1641827423248 | 11 | Thread-0 | 没被中断继续开
1641827423248 | 11 | Thread-0 | 没被中断继续开
1641827423248 | 11 | Thread-0 | 没被中断继续开
1641827423248 | 11 | Thread-0 | 没被中断继续开
1641827423248 | 11 | Thread-0 | 没被中断继续开
*/
}
}
要点:
如果调用sleep(timeout)之前或正在sleep的过程中,线程就有了中断标记位,就不会去睡觉了,立马跳到catch(interruptException)执行余下的代码:(注意时间戳)
sleep之前
public class BeforehandInterrupt {
public static void main(String[] args) {
Thread.currentThread().interrupt();
try {
SmallTool.printTimeAndThread("开始睡眠");
Thread.sleep(1000);
} catch (InterruptedException e) {
SmallTool.printTimeAndThread("发生中断");
}
SmallTool.printTimeAndThread("结束睡眠");
/**
* 运行结果:看时间戳
* 1641827782934 | 1 | main | 开始睡眠
1641827782934 | 1 | main | 发生中断
1641827782934 | 1 | main | 结束睡眠
*
*/
}
}
sleep过程中
public class ThreadInterrupt {
public static void main(String[] args) {
Thread carTwo = new Thread(() -> {
SmallTool.printTimeAndThread("卡丁2号 准备过桥");
SmallTool.printTimeAndThread("发现1号在过,开始等待");
try {
Thread.sleep(5000);
} catch (InterruptedException e) {
SmallTool.printTimeAndThread("卡丁2号 开始过桥");
}
SmallTool.printTimeAndThread("卡丁2号 过桥完毕");
});
Thread carOne = new Thread(() -> {
SmallTool.printTimeAndThread("卡丁1号 开始过桥");
int timeSpend = new Random().nextInt(500) + 1000;
SmallTool.sleepMillis(timeSpend);
SmallTool.printTimeAndThread("卡丁1号 过桥完毕 耗时:" + timeSpend);
SmallTool.printTimeAndThread("卡丁2号的状态" + carTwo.getState());
//如果不加这句,carTwo的InterruptedException打印不会触发,而且要等完5秒才打印卡丁2号过桥完毕
//加上的话,立刻中断并继续执行下去
carTwo.interrupt();
});
carOne.start();
carTwo.start();
}
/**
* 运行结果:
* (注释carTwo.interrupt,,看前面的时间戳)
1641822835997 | 12 | Thread-1 | 卡丁1号 开始过桥
1641822835999 | 11 | Thread-0 | 卡丁2号 准备过桥
1641822835999 | 11 | Thread-0 | 发现1号在过,开始等待
1641822837375 | 12 | Thread-1 | 卡丁1号 过桥完毕 耗时:1375
1641822837375 | 12 | Thread-1 | 卡丁2号的状态TIMED_WAITING
1641822846008 | 11 | Thread-0 | 卡丁2号 过桥完毕
*
* 不注释
1641824076546 | 12 | Thread-1 | 卡丁1号 开始过桥
1641824076548 | 11 | Thread-0 | 卡丁2号 准备过桥
1641824076548 | 11 | Thread-0 | 发现1号在过,开始等待
1641824077600 | 12 | Thread-1 | 卡丁1号 过桥完毕 耗时:1050
1641824077600 | 12 | Thread-1 | 卡丁2号的状态TIMED_WAITING
1641824077600 | 11 | Thread-0 | 卡丁2号 开始过桥
1641824077601 | 11 | Thread-0 | 卡丁2号 过桥完毕
*
*/
}
关于InterruptedException的抛出
/**
* Thrown when a thread is waiting, sleeping, or otherwise occupied,
* and the thread is interrupted, either before or during the activity.
* Occasionally a method may wish to test whether the current
* thread has been interrupted, and if so, to immediately throw
* this exception. The following code can be used to achieve
* this effect:
* <pre>
* if (Thread.interrupted()) // Clears interrupted status!
* throw new InterruptedException();
* </pre>
*/
public
class InterruptedException extends Exception
余下略
可以看到InterruptedException 源码的注释,什么时候抛这个异常?当线程在等待、睡眠或被其他占用的时候,线程被打断,无论在运行之前还是期间,则立马抛出异常。
比如在调用sleep(timeout)的时候,该线程会处于timed_waiting的状态;Object.wait()就是waiting,其加上timeout参数,就是timed_waiting,上述的注释已经说明清楚。
无故设置中断标记位
再者,比如某线程运行得好好的,runnable状态,不会变成waiting、timed_waiting的状态,这时无缘无故给它一个t.interrupt(),其实对它是没有影响的,仅仅给它弄了个中断标记位,并不会影响它执行程序,如果后续有需要对它的中断标记状态做点什么事情,完全就可进行判断其中断标记位来操作。
网友评论