1、线程各属性纵览
属性名称 | 用户 |
---|---|
编号(ID) | 每个线程有自己的ID,用于标识不同的线程 |
名称(Name) | 作用让用户或程序员在开发、调试或运行过程中,更容易区分每个不同的线程、定位问题等 |
是否是守护线程(isDaemon) | true代表该线程是【守护线程】,false代表线程是非守护线程,也就是【用户线程】 |
优先级(Priority) | 优先级这个属性的目的是告诉线程调度器,用户希望哪些线程相对多运行、哪些少运行 |
2、线程ID
/**
* Id
*
* @author venlenter
* @Description: ID从1开始,JVM运行起来后,我们自己创建的线程的ID早已不是2
* @since unknown, 2020-04-26
*/
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:11
//getId内部调用是nextThreadID
//thread.getId = nextThreadID()
//private static synchronized long nextThreadID() {
// return ++threadSeqNumber;
// }
3、线程名字、守护线程
3.1 线程名字
3.1.1 默认线程名字源码分析
- "Thread-" + 自增数
public Thread() {
init(null, null, "Thread-" + nextThreadNum(), 0);
}
private static synchronized int nextThreadNum() {
return threadInitNumber++;
}
3.1.2 修改线程的名字(代码演示、源码分析)
Thread thread = new Thread();
System.out.println("子线程初始名字:" + thread.getName());
thread.setName("FlyThread-1");
System.out.println("子线程修改后的名字:" + thread.getName());
//输出结果
子线程初始名字:Thread-0
子线程修改后的名字:FlyThread-1
3.2 守护线程
3.2.1 作用:给用户线程提供服务
3.2.2 三个特性
- 线程类型默认继承自父线程(守护线程的子线程也是守护线程)
- 通常守护线程都是由JVM自动启动的
- 不影响JVM退出:JVM退出只会考虑是否还有用户线程
3.2.3 守护线程的常见面试问题
(1)守护线程和普通线程的区别
- 整体无区别
- 唯一区别在于JVM的离开:用户线程会影响JVM的停止,而守护线程不影响
- 作用不同:用户线程是执行逻辑的,而守护线程是给用户线程提供服务的
(2)我们是否需要给线程设置为守护线程?thread.setDaemon(true);
- 不应该把自己的用户线程设置为守护线程。
- 例如:如果设置了用户线程为守护线程,JVM发现只有一个守护线程,就中止退出了,导致程序逻辑没有走完。
- 其实JVM本身提供的守护线程就已经足够了
4、线程优先级
10个级别,默认5
- 引申面试题:我们应该如何应用线程优先级来帮助程序运行?有哪些禁忌?
- 不同的操作系统如何处理优先级问题?
程序设计不应依赖于优先级
- 不同操作系统不一样
- 优先级会被操作系统改变
5、各属性总结
属性名称 | 用途 | 注意事项 |
---|---|---|
编号(ID) | 标识不同的线程 | 线程回收后,id被后续创建的线程使用;无法保证id的唯一性(之前线程id,跟后续线程id不一定是同一个线程,可能是回收后后续创建的);不允许修改id |
名称(Name) | 定位问题 | 可以设置一个清晰有意义的名字(方便跟踪定位);默认的名称是Thread-0/1/2/3 |
是否是守护线程(isDaemon) | 守护线程/用户线程 | 二选一;继承父线程;setDaemon |
优先级(Priority) | 告诉线程调度器,哪些线程相对多运行、哪些少运行 | 默认和父线程的优先级相等,共有10个等级,默认5;不应依赖优先级 |
笔记来源:慕课网悟空老师视频《Java并发核心知识体系精讲》