线程属性
线程各属性
线程ID
id从 1 开始计数,因为在源码中是如下实现的,初始值设置为0,id是先自增再返回
private volatile int threadStatus = 0;
private static synchronized long nextThreadID() {
return ++threadSeqNumber;
}
- 现在来演示以下线程的id
public class Id {
public static void main(String[] args) {
Thread thread = new Thread();
System.out.println("主线程ID " + Thread.currentThread().getId());
System.out.println("子线程ID " + thread.getId());
}
}
/*
* 主线程ID 1
子线程ID 20
* */
主线程是起始线程所以id为1,但是上面代码中我们新创建的线程id为 20 ,而不是2
解释上述问题可以用debug的方式来看
在打印子线程id的那行代码打上一个断点,看图片中箭头所指的方向可知,主线程之外,除了我们自己创建的线程,JVM还创建了很多线程,所以导致我们创建的线程id不为2
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-AjkryBtp-1674877827964)(C:\Users\Lenovo\AppData\Roaming\Typora\typora-user-images\image-20230128112046624.png)]
线程名字
默认线程名字源码
当我们没有指定线程的名字时,线程会用Thread-0,Thread-1这种形式命名,后面的数字会自增
public Thread() {
init(null, null, "Thread-" + nextThreadNum(), 0);
}
private static int threadInitNumber;
private static synchronized int nextThreadNum() {
return threadInitNumber++;
}
设置线程名字源码
创建线程之后可以用setName方法来对线程的名字进行更改
但是native层面的名字,线程启动之后就不能再被更改
public final synchronized void setName(String name) {
checkAccess();
if (name == null) {
throw new NullPointerException("name cannot be null");
}
this.name = name;
// 检查线程是否启动
if (threadStatus != 0) {
setNativeName(name);
}
}
/* Java thread status for tools,
* initialized to indicate thread 'not yet started'
*/
private volatile int threadStatus = 0;
private native void setNativeName(String name);
守护线程
作用:为其他线程提供服务,比如:垃圾处理器
特性
- 线程类型默认继承自父线程
我们自己创建的线程为用户线程,因为父线程就是用户线程
守护线程创建的子线程,也为守护线程
如果用用户线程创建守护线程,需要用setDaemon()方法手动更改线程的属性
- 通常所有的守护线程都由JVM来启动
- 守护线程不影响JVM的退出
和普通线程的区别
整体上两者并无区别,区别在于,守护线程不会影响JVM的退出
用户线程负责执行逻辑,守护线程负责服务于用户线程
程都由JVM来启动
- 守护线程不影响JVM的退出
和普通线程的区别
整体上两者并无区别,区别在于,守护线程不会影响JVM的退出
用户线程负责执行逻辑,守护线程负责服务于用户线程