Hi~!这里是奋斗的明志,很荣幸您能阅读我的文章,诚请评论指点,欢迎欢迎 ~~
🌱🌱个人主页:奋斗的明志
🌱🌱所属专栏:Java多线程
📚本系列文章为个人学习笔记,在这里撰写成文一为巩固知识,二为展示我的学习过程及理解。文笔、排版拙劣,望见谅。
目录
- 一、线程的状态
- 1.观察线程的所有状态
- 2.线程状态和状态转移的意义
- 二、 等待一个线程 - join()
- 三、获取当前线程引用
- 四、休眠当前线程
一、线程的状态
- 之前谈到的“进程的状态”,更准确的说,是“线程的状态”,或者叫做“PCB的状态”
- Java 中,对于线程的状态,大概是分成 6 中不同的状态~~
1.观察线程的所有状态
public static void main(String[] args) {
for (Thread.State state : Thread.State.values()){
System.out.println(state);
}
}
- NEW:Thread对象有了,还没调用start,系统内部的线程还未创建
public static void main(String[] args) throws InterruptedException {
Thread t = new Thread(() -> {
System.out.println("hello");
});
System.out.println("start之前的状态:" + t.getState());
t.start();
t.join();
System.out.println("start之后的状态:" + t.getState());
}
-
TERMINATED:线程已经终止了,内核中的线程已经销毁了,Thread还在
-
RUNNABLE:就绪状态(可运行状态)(指这个线程“随叫随到”,正在CPU上执行或者没在CPU上执行,随时可以调度到CPU上执行)
-
WAITING:死等进入的阻塞
public static void main(String[] args) throws InterruptedException {
Thread t = new Thread(() -> {
while (true){
System.out.println("hello thread");
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
}
});
t.start();
//死等版本的 join
t.join();
}
- TIMED_WAITING:带有超时时间的等
public static void main(String[] args) throws InterruptedException {
Thread t = new Thread(() -> {
while (true){
System.out.println("hello thread");
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
}
});
t.start();
//带有超时时间版本的 join
t.join(3600 * 1000);
}
- BLOCKED: 这几个都表示排队等着其他事情
2.线程状态和状态转移的意义
还是我们之前的例⼦:
刚把李四、王五找来,还是给他们在安排任务,没让他们行动起来,就是 NEW
状态;
当李四、王五开始去窗⼝排队,等待服务,就进入到 RUNNABLE
状态。该状态并不表示已经被银行工作人员开始接待,排在队伍中也是属于该状态,即可被服务的状态,是否开始服务,则看调度器的调度;
当李四、王五因为⼀些事情需要去忙,例如需要填写信息、回家取证件、发呆⼀会等等时,进⼊
BLOCKED
、 WATING
、 TIMED_WAITING
状态,⾄于这些状态的细分,我们以后再详解;
如果李四、王五已经忙完,为 TERMINATED
状态。
所以,之前我们学过的 isAlive() 方法,可以认为是处于不是 NEW 和 TERMINATED 的状态都是活着的。
观察 1: 关注 NEW
、 RUNNABLE
、 TERMINATED
状态的转换
public static void main(String[] args) {
Thread t = new Thread(() -> {
for (int i = 0; i < 1000_0000; i++) {
}
},"李四");
System.out.println(t.getName() + ":" + t.getState());
t.start();
while (t.isAlive()){
System.out.println(t.getName() + ":" + t.getState());
}
System.out.println(t.getName() + ":" + t.getState());
}
观察 2: 关注 WAITING
、 BLOCKED
、 TIMED_WAITING
状态的转换
public static void main(String[] args) {
final Object object = new Object();
Thread t1 = new Thread(new Runnable() {
@Override
public void run() {
synchronized (object){
while (true){
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
}
}
}
},"t1");
t1.start();
Thread t2 = new Thread(new Runnable() {
@Override
public void run() {
synchronized (object){
System.out.println("hehe");
}
}
},"t2");
t2.start();
}
使用 jconsole 可以看到 t1 的状态是
TIMED_WAITING
, t2 的状态是BLOCKED
- 修改上面的代码, 把 t1 中的 sleep 换成 wait
public static void main(String[] args) {
final Object object = new Object();
Thread t1 = new Thread(new Runnable() {
@Override
public void run() {
synchronized (object){
while (true){
try {
object.wait();
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
}
}
}
},"t1");
t1.start();
Thread t2 = new Thread(new Runnable() {
@Override
public void run() {
synchronized (object){
System.out.println("hehe");
}
}
},"t2");
t2.start();
}
使⽤ jconsole 可以看到 t1 的状态是
WAITING
结论:
BLOCKED
表示等待获取锁,WAITING
和TIMED_WAITING
表示等待其他线程发来通知.TIMED_WAITING
线程在等待唤醒,但设置了时限;WAITING
线程在无限等待唤醒
二、 等待一个线程 - join()
有时,我们需要等待⼀个线程完成它的⼯作后,才能进行自己的下⼀步⼯作。例如,张三只有等李四转账成功,才决定是否存钱,这时我们需要一个方法明确等待线程的结束。
方法 | 说明 |
---|---|
public void join | 等待线程结束 |
public void join(long millis) | 等待线程结束,最多等 millis 毫秒 |
public void join(long millis,int nanos) | 同理,更高精度 |
public static void main(String[] args) throws InterruptedException {
Runnable target = () -> {
for (int i = 0; i < 3; i++) {
System.out.println(Thread.currentThread().getName()
+ ":我还在工作!");
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
}
System.out.println(Thread.currentThread().getName() + ":我结束了!");
};
Thread t1 = new Thread(target,"李四");
Thread t2 = new Thread(target,"王五");
System.out.println("先让李四开始工作");
t1.start();
t1.join();
System.out.println("李四工作结束了,开始让王五开始工作");
t2.start();
t2.join();
System.out.println("王五工作结束了");
}
三、获取当前线程引用
方法 | 说明 |
---|---|
public static void currentThread() | 返回当前线程的引用 |
四、休眠当前线程
也是我们比较熟悉⼀组⽅法,有⼀点要记得,因为线程的调度是不可控的,所以,这个方法只能保证实际休眠时间是大于等于参数设置的休眠时间的。
public static void main(String[] args) throws InterruptedException {
System.out.println("start:" + System.currentTimeMillis());
Thread.sleep(3 * 1000);
System.out.println("end:" + System.currentTimeMillis());
}
这里有一定的误差