java多线程wait notify/notify all join 分析使用
一、线程状态
先上个图

从上图可以看出 一个线程一共有5个状态
1、新建状态
使用new 关键字和Thread类 或者其子类建立一个线程对象后,该线程就处于新建状态,它保持这个状态直到程序start()这个线程。
2、就绪状态
当线程对象调用start()方法之后,该线程进入就绪状态,就绪状态的线程处于就绪队列中,要等待JVM里线程调度器的调度
3、运行状态
如果就绪状态的线程获取CPU资源,就可以执行run()方法,此时线程便处于运行状态,处于运行状态的线程最为复杂,它可以变为阻塞状态、就绪状态和死亡状态
4、阻塞状态
如果一个线程执行了sleep()睡眠、suspend()挂起等方法后,失去所占资源之后,该线程就从运行状态进入阻塞状态。在睡眠时间已到或获得设备资源后可以重新进入就绪状态。可以分为三种:
1) 等待阻塞
运行状态中,执行了wait()方法,使线程进入到等待阻塞状态
2)同步阻塞
线程在获取synchronized同步锁失败(因为同步锁被其他线程占用)
3) 其他堵塞
通过调用线程的sleep()或join()发出I/O请求时,线程就会进入到阻塞状态。当sleep()状态超时,join()等待线程终止或超时,或者I/O处理完毕,线程重新转入就绪状态
4)死亡状态
一个运行状态的线程完成任务或者其他终止条件发生时,该线程就切换到终止状态
二、wait 与 notify /notifyAll
一个对象只有一个锁,参与该对象锁竞争的线程,与参与其他对象锁竞争的线程无关.线程竞争,对应一个对象的一个锁
wait: 当线程对象执行wait()时,会把当前的锁释放,然后让出CPU,进入阻塞状态。
notify /notifyAll: 执行该方法后会 唤醒一个处于等待该 对象锁 的线程,然后继续往下执行,直到执行完退出对象锁锁住的区域(synchronized修饰的代码块)后再释放锁。所以在实际编程中,我们应该尽量在线程调用notify/notifyAll()后,立即退出临界区。即不要在notify/notifyAll()后面再写一些耗时的代码
wait 与 notify/notifyAll 方法一般是成对出现,并且必须在同步代码块中使用,即要先对调用对象加锁
给大佬奉茶:
package com.test.thread;
import java.text.SimpleDateFormat;
import java.util.Date;
public class Clock {
private String currentTime;
private static final Object obj = new Object();
/**
*获取当前时间
*/
class TimeThread extends Thread{
@Override
public void run() {
String pattern = "yyyy-MM-dd hh:mm:ss";
SimpleDateFormat sdf = new SimpleDateFormat(pattern);
currentTime = sdf.format(new Date());
synchronized (obj){
obj.notify(); //唤醒一个处于等待该 对象锁 的线程
}
}
}
/**
* 显示时间
*/
class ShowThread extends Thread{
@Override
public void run() {
synchronized (obj){
if (currentTime == null){
try {
obj.wait(); //进入阻塞状态 并没有立即释放对象锁
} catch (InterruptedException e) {
e.printStackTrace();
}
}
System.out.println("现在的时间是:"+currentTime); //直到同步代码块区域 都执行完毕后 才释放对象锁
}
}
}
public static void main(String[] args) {
Clock clock = new Clock();
TimeThread timeThread = clock.new TimeThread();
ShowThread showThread = clock.new ShowThread();
timeThread.start();
showThread.start();
}
}
三、join方法
线程对象执行join方法,线程进入阻塞状态,直到调用该方法的线程结束后再继续向下执行,从而实现线程的顺序执行
奉茶:
package playground;
import java.text.SimpleDateFormat;
import java.util.Date;
public class Clock {
String currentTime;
//显示时间
class ShowThread extends Thread{
TimeThread timeThread ;
public ShowThread(TimeThread timeThread) {
this.timeThread = timeThread;
}
@Override
public void run() {
try {
//join()所在线程堵塞,直到timeThread线程执行完毕
timeThread.join();
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("当前时间为:"+currentTime);
}
}
//获取时间
class TimeThread extends Thread{
@Override
public void run() {
String pattern = "yyyy-MM-dd HH:mm:ss";
SimpleDateFormat sdf = new SimpleDateFormat(pattern);
currentTime = sdf.format(new Date());
}
}
public static void main(String[] args) {
Clock clock = new Clock();
TimeThread timethread = clock.new TimeThread();
ShowThread showThread = clock.new ShowThread(timethread);
timethread.start();
showThread.start();
}
}
Java线程状态与控制
本文深入解析Java线程的五种状态:新建、就绪、运行、阻塞和死亡,详细阐述wait、notify/notifyAll及join方法的使用场景与机制。通过实例代码展示线程间如何协调工作,实现高效并发。
1554

被折叠的 条评论
为什么被折叠?



