多线程wait和notify 如何知道是被通知唤醒还是超时唤醒呢?【松思园】

wait/notify/notifyAll的作用是为了避免轮询带来的性能损失,而产生轮询的条件是多个线程对同一个资源进行操作。即,一般在synchronized 同步代码块里使用 wait()、notify()、notifyAll() 方法;

  • obj.wait() 让进入 object 锁的线程到等待状态;
  • obj.notify() 在object 上正处于等待状态的线程中挑一个唤醒;
  • obj.notifyAll() 让 object 上正处于等待状态的所有线程全部唤醒;

他们都是线程之间进行写作的手段,都属于Object 对象的方法,因此必须要获得此对象的锁,才能调用这几个方法。

@Slf4j
public class WaitNotifyDemo {

	static final Object objectLock = new Object();

	public static void main(String[] args) {
		Thread.currentThread().setName("Main主线程");
		synchronized (objectLock) {
			try {
				objectLock.wait();
				log.info("主线程进入等待状态");
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
		}
	}
} 

通过运行可以知道 线程在运行后,主线程一直处于等待状态,等待后,下面的代码不在运行


重点来了:wait 可传参也可以不传参,传参的话,表示只等待多少时间,不传参的话会一直等待,需要其他线程进行唤醒,那两种方式都能唤醒,又如何做区分呢?
这里我们将采用全局变量做标记的方式,还有人建议使用 时间进行记录的方式,但是这种方式不能够很精确的判断。

场景:有三个线程, A线程在做饭(5 s 做好),B和C线程吃饭, B和C先准备碗筷等工作,然后等待A线程做好饭才能吃, 然而 C 线程吃饭比较有脾气,等你 3 s ,还做不好饭菜,他就不吃了,走人了。

代码实现:

@Slf4j
public class WaitNotifyDemo02 {

	private static Boolean flag;
	final static Object objectFood = new Object();

	public static void main(String[] args) throws InterruptedException {
		Thread.currentThread().setName("【A线程做饭】");
		Thread thread01 = new Thread(() -> {
			synchronized (objectFood) {
				log.info("B线程准备碗筷中……");
				log.info("B线程准备好了碗筷,等待饭菜做好……");
				try {
					flag = true;
					objectFood.wait(3000);
					if (flag) {
						log.info("B线程等急了,生气走了……");
					} else {
						log.info("B线程开始了享用美味的饭菜……");
					}
				} catch (InterruptedException e) {
					e.printStackTrace();
				}
			}
		}, "【B线程吃饭】");
		Thread thread02 = new Thread(() -> {
			synchronized (objectFood) {
				log.info("C线程准备碗筷中……");
				log.info("C线程准备好了碗筷,等待饭菜做好……");
				try {
					objectFood.wait();
					log.info("C线程开始了享用美味的饭菜……");
				} catch (InterruptedException e) {
					e.printStackTrace();
				}
			}
		}, "【C线程吃饭】");
		thread01.start();
		thread02.start();
		log.info("A线程在努力的制作饭菜中………………");
		Thread.sleep(5000);
		log.info("A线程用时5秒做好了饭菜……");
		synchronized (objectFood) {
			// objectFood.notify();
			// log.info("A线程随机唤醒B或C可以吃饭了……");
			objectFood.notifyAll();
			flag = false;
			log.info("A线程唤醒B和C可以吃饭了……");
		}
	}
}

运行结果:

14:02:33.186 [【A线程做饭】] INFO  并发编程.WaitNotifyDemo02 - A线程在努力的制作饭菜中………………
14:02:33.186 [【B线程吃饭】] INFO  并发编程.WaitNotifyDemo02 - B线程准备碗筷中……
14:02:33.191 [【B线程吃饭】] INFO  并发编程.WaitNotifyDemo02 - B线程准备好了碗筷,等待饭菜做好……
14:02:33.191 [【C线程吃饭】] INFO  并发编程.WaitNotifyDemo02 - C线程准备碗筷中……
14:02:33.191 [【C线程吃饭】] INFO  并发编程.WaitNotifyDemo02 - C线程准备好了碗筷,等待饭菜做好……
14:02:36.200 [【B线程吃饭】] INFO  并发编程.WaitNotifyDemo02 - B线程等急了,生气走了……
14:02:38.196 [【A线程做饭】] INFO  并发编程.WaitNotifyDemo02 - A线程用时5秒做好了饭菜……
14:02:38.196 [【A线程做饭】] INFO  并发编程.WaitNotifyDemo02 - A线程唤醒B和C可以吃饭了……
14:02:38.197 [【C线程吃饭】] INFO  并发编程.WaitNotifyDemo02 - C线程开始了享用美味的饭菜……
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值