java多线程wait notify/notify all join 分析使用

Java线程状态与控制
本文深入解析Java线程的五种状态:新建、就绪、运行、阻塞和死亡,详细阐述wait、notify/notifyAll及join方法的使用场景与机制。通过实例代码展示线程间如何协调工作,实现高效并发。

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();
	}
}

 

 

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值