1 类注释
程序中执行的线程。JVM允许应用程序拥有多个并发运行的执行线程。
每个线程都有一个优先级。优先级高的线程优先于优先级低的线程执行。每个线程可能被标记为守护线程,也可能不被标记为守护线程。
当在某个线程中运行的代码创建一个新 Thread 对象时,新线程的优先级最初设置为创建线程的优先级,并且只有在创建线程是一个守护线程时,新线程才是守护线程。
当JVM启动时,通常有一个非守护的线程(它通常调用某个指定类的main方法)。JVM 继续执行线程,直到发生以下任何一种情况时停止:
Runtime 类的 exit 方法已被调用,且安全管理器已允许执行退出操作(比如调用 Thread.interrupt 方法)
不是守护线程的所有线程都已死亡,要么从对 run 方法的调用返回,要么抛出一个在 run 方法之外传播的异常
每个线程都有名字,多个线程可能具有相同的名字,Thread 有的构造器如果没有指定名字,会自动生成一个名字。
2 线程的基本概念
2.1 线程的状态
源码中一共枚举了六种线程状态
![](https://img.laitimes.com/img/__Qf2AjLwojIjJCLyojI0JCLicmbw5iNwEDOxgzY4IWO3ETM2YTOxUmM0UzYzcjMlRmY3Y2Ym9CX5d2bs92Yl1iclB3bsVmdlR2LcNWaw9CXt92Yu4GZjlGbh5yYjV3Lc9CX6MHc0RHaiojIsJye.png)
线程的状态机
2.1.1 状态机说明
当调用start(),进入RUNNABLE,当前线程sleep()结束,其他线程join()结束,等待用户输入完毕,某个线程拿到对象锁,这些线程也将进入RUNNABLE
当线程运行完成、被打断、被中止,状态都会从 RUNNABLE 变成 TERMINATED
如果线程正好在等待获得 monitor lock 锁,比如在等待进入 synchronized 修饰的代码块或方法时,会从 RUNNABLE 转至 BLOCKED
WAITING 和 TIMED_WAITING 类似,都表示在遇到 Object#wait、Thread#join、LockSupport#park 这些方法时,线程就会等待另一个线程执行完特定的动作之后,才能结束等待,只不过 TIMED_WAITING 是带有等待时间的
2.2 线程的优先级
优先级代表线程执行的机会的大小,优先级高的可能先执行,低的可能后执行,在 Java 源码中,优先级从低到高分别是 1 到 10,线程默认 new 出来的优先级都是 5,源码如下:
分别为最低,普通(默认优先级),最大优先级
2.3 守护线程
创建的线程默认都是非守护线程。
- 创建守护线程时,需要将 Thread 的 daemon 属性设置成 true
-
终于有人能把Thread讲清楚了(上)1 类注释2 线程的基本概念3 线程的初始化的两种方式 - 守护线程的优先级很低,当 JVM 退出时,是不关心有无守护线程的,即使还有很多守护线程,JVM 仍然会退出。
在工作中,我们可能会写一些工具做一些监控的工作,这时我们都是用守护线程去做,这样即使监控抛出异常,也不会影响到业务主线程,所以 JVM 也无需关注监控是否正在运行,该退出就退出,所以对业务不会产生任何影响。
3 线程的初始化的两种方式
无返回值的线程主要有两种初始化方式:
3.1 继承 Thread
看下 start 方法的源码:
public synchronized void start() {
/**
* 对于由VM创建/设置的主方法线程或“系统”组线程,不调用此方法。
* 将来添加到此方法中的任何新功能可能也必须添加到VM中。
*
* 零状态值对应于状态“NEW”。
* 因此,如果没有初始化,直接抛异常
*/
if (threadStatus != 0)
throw new IllegalThreadStateException();
/*
* 通知组此线程即将start,以便可以将其添加到组的线程列表中
* 并且可以减少组的unstarted线程的计数
*/
group.add(this);
// started 是个标识符,在处理一系列相关操作时,经常这么设计
// 操作执行前前标识符是 false,执行完成后变成 true
boolean started = false;
try {
// 创建一个新的线程,执行完成后,新的线程已经在运行了,即 target 的内容已在运行
start0();
// 这里执行的还是 main 线程
started = true;
} finally {
try {
// 若失败,将线程从线程组中移除
if (!started) {
group.threadStartFailed(this);
}
// Throwable 可以捕捉一些 Exception 捕捉不到的异常,比如子线程抛出的异常
} catch (Throwable ignore) {
/*
* 什么也不做。
* 如果start0抛出一个Throwable,那么它将被传递到调用堆栈
*/
}
}
}
// 开启新线程使用的是 native 方法
private native void start0();
注意上面提到的的
threadStatus
变量
用于工具的Java线程状态,初始化以指示线程“尚未启动”