前言
Java并发知识体系持续更新:https://blog.csdn.net/m0_46144826/category_9881831.html
开始之前老规矩,把源码放上:
- Thread 源码解读注释:https://github.com/qianwei4712/JDK1.8.0.25-read/blob/master/src/main/java/java/lang/Thread.java
- Object 源码解读注释:https://github.com/qianwei4712/JDK1.8.0.25-read/blob/master/src/main/java/java/lang/Object.java
一个线程执行完毕之后会自动结束,如果在运行过程中发生异常也会提前结束。
线程中断是一个非常重要的概念,中断线程是取消任务最好的方法。
在 Java 的 Thread
类中,提供了以下三个关于线程中断的 public
方法:
void interrupt()
,中断线程。static boolean interrupted()
,测试当前线程是否已被中断。通过此方法可以清除线程的中断状态。boolean isInterrupted()
,测试线程是否已经中断,线程的中断状态不受该方法的影响。
这三个是线程的公共方法,但是它的最底层是两个 native 方法:
private native void interrupt0(); //中断线程
/**
* 测试某些线程是否已被中断。线程的中断状态不受此方法的影响。
* ClearInterrupted参数决定线程中断状态是否被重置,若为true则重置。
*/
private native boolean isInterrupted(boolean ClearInterrupted);
从这里就可以发现:
线程的中断状态,并不是由 Java 来决定。实际上,Thread 类中并没有维护线程的中断状态。
协作式和抢占式
然后,就有了下一个问题:
中断状态是个啥玩意儿???线程中断难道不是终止线程嘛?为什么还会有状态?Thread 类里面也没有这个状态变量啊,难道操作系统内给线程添加了这个状态?
所以,又又又又得百度去咯。。。根据各位大佬们的博客,个人感觉应该是这样的:
- 明确线程中断状态不是 Thread 类的标志位,而是操作系统中对线程的中断标志。
这一结论来自 native
方法:
/**
* 测试某些线程是否已被中断。线程的中断状态不受此方法的影响。
* ClearInterrupted参数决定线程中断状态是否被重置,若为true则重置。
*/
private native boolean isInterrupted(boolean ClearInterrupted);
很明显了,在操作系统对线程的管理中,确实存在一个中断状态的标志位。
- 操作系统调度线程的方式:协作式、抢占式
- 协作式:线程自己的工作执行完后,要主动通知调度切换到另一个线程上。 如果一个线程编写有问题,一直不告知系统进行线程切换,那么程序就会一直阻塞在那里。线程的执行时间由自身掌控。
- 抢占式:线程将由调度来分配执行时间,线程的切换不由线程自身决定。 不会出现一个线程导致整个进程阻塞的问题。
Java 的线程中断,也作为协作式中断,调用 interrupt()
方法最终也只是更改操作系统中的中断标志位,线程是否中断,由线程自身决定。
isInterrupted()
测试线程是否已经中断,线程的中断状态不受该方法的影响。
/**
* 测试此线程是否已被中断。线程的中断状态不受此方法的影响。
* <p>如果中断时,线程并没有存活,那么该方法返回 false。意思就是,如果线程还没有 start 启动,或者已经消亡,那么返回依然是 false.
* @return 如果该线程已被中断,返回true;否则返回 false
*/
public boolean isInterrupted() {
//不清除中断状态
return isInterrupted(false);
}
这是最基础的判断中断状态,且不更改 OS 线程中断标志位。可以对照上面的 native 方法阅读。特别的记一下这两句:
如果线程还没有 start 启动,或者已经消亡,那么返回依然是 false。中断状态只代表是否有线程调用中断方法。
举个栗子看下效果就行:
public static class Example extends Thread{
@Override
public void run