Thread 的常见构造方法
- 在创建线程的时候,是可以给线程起名字的。默认为 Thread-0 、Thread-1…
- 不会影响线程执行效果,可以更好地进行管理
ThreadGroup
-线程组
- 把多个线程放到一组里,方便统一的设置线程的一些属性
- 不过现在很少用到,线程相关属性用的也不太多,更多会用到“线程池”
Thread 的几个常见属性
- 通常情况下,一个 thread 对象,就是对应到系统内部的一个线程(PCB),但也可能会存在一个情况——Thread 对象存在,但是系统内部的线程已经没了/还没创建
- 设置不同的优先级会影响到系统的调度。这里的影响是基于“统计”规则的影响,直接肉眼观察,很难看到效果
前台线程:
[!NOTE] 后台线程/前台线程
- 若某个线程在执行过程中,可以阻止进程结束,此时这个线程就是“前台线程”
- 若某个线程在执行过程中,不能阻止进程结束(虽然线程在执行着,但是进程要结束了,此时这个线程也会随之被带走)这样的线程就是“后台线程”,也叫做“守护线程”
- 一个进程中,前台线程可以有多个(创建线程的时候默认就是前台的),必须所有的前台线程都结束,进程才能结束
- 前台线程就相当于是饭桌上的“老大”,若只有一个老大,他走了饭局就散了;若有很多老大,那得他们一起商量结不结束;后台线程就相当与是后台上的我,走不走无所谓,小透明
public class test3 { public static void main(String[] args) { System.out.println("hello main"); Thread t = new Thread(() -> { while(true){ System.out.println("hello thread"); try{ Thread.sleep(1000); }catch (InterruptedException e){ throw new RuntimeException(e); } } }); //将t线程设为后台进程,只要main进程结束,整个进程就结束了 t.setDaemon(true); t.start(); } }
把 t 进程设为后台进程后,程序中就只有
main
一个前台线程了,所以只要main
执行完,整个进程就结束了又因为线程是并发执行的,所以
t
线程中的执行逻辑可能赶在main
线程执行前执行所以最终打印结果一定有“
hello main
”,可能也有“hello thread
”
- 前台进程和后台进程唯一的区别就是控制结束时间
- 一个进程中必须得有一个前台线程
是否存活:
- 代码中,创建的 newThread 对象的生命周期和内核中实际的线程是不一样的,可能会出现 Thread 对象仍然存在,但内核中的线程不存在了这种情况
- 调用 start 之前,内核中还没有创建线程
- 线程的 run 执行完毕了,内核的线程就没有了,但是 Thread 对象仍然存在
- 不会出现 Thread 对象不存在,线程还存在的这种情况
isAlive()
:
- 为 true,表示内核线程存在
- 为 false,表示内核线程没了
public static void main(String[] args) throws InterruptedException { Thread t = new Thread(() -> { for(int i = 0; i < 3; i++) { System.out.println("hello thread"); try { Thread.sleep(1000); } catch (InterruptedException e) { throw new RuntimeException(e); } } }); System.out.println(t.isAlive()); //false t.start(); System.out.println(t.isAlive()); //true Thread.sleep(5000); System.out.println(t.isAlive()); //false }
- 第一次打印
false
:此时线程还未创建- 第二次打印
true
:此时线程创建了,但还没结束- 第三次打印
false
:由于 main 线程此时还在休眠,所以只考虑 t 线程,又因为 t 线程的 run 在五秒之内已经执行完了,所以线程就没有了
- 由于线程之间的调度顺序是不确定的,如果两个线程都是 sleep(3000),此时,当时间一到,两个线程谁先执行,谁后执行是不一定的,所以打印出 true 还是 false 是不确定的
- 但不一定不是指双方概率相等,双方概率会随着系统的不同,代码运行环境的不同而改变