Java多线程学习之wait、notify/notifyAll 详解
public class K {
//状态锁
private Object lock;
//条件变量
private int now,need;
public void produce(int num){
//同步
synchronized (lock){
//当前有的不满足需要,进行等待,直到满足条件
while(now < need){
try {
//等待阻塞
lock.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("我被唤醒了!");
}
// 做其他的事情
}
}
}

import java.util.LinkedList; /**
* 生产者和消费者的问题
* wait、notify/notifyAll() 实现
*/
public class Storage1 implements AbstractStorage {
//仓库最大容量
private final int MAX_SIZE = 100;
//仓库存储的载体
private LinkedList list = new LinkedList(); //生产产品
public void produce(int num){
//同步
synchronized (list){
//仓库剩余的容量不足以存放即将要生产的数量,暂停生产
while(list.size()+num > MAX_SIZE){
System.out.println("【要生产的产品数量】:" + num + "\t【库存量】:"
+ list.size() + "\t暂时不能执行生产任务!"); try {
//条件不满足,生产阻塞
list.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
} for(int i=0;i<num;i++){
list.add(new Object());
} System.out.println("【已经生产产品数】:" + num + "\t【现仓储量为】:" + list.size()); list.notifyAll();
}
} //消费产品
public void consume(int num){
synchronized (list){ //不满足消费条件
while(num > list.size()){
System.out.println("【要消费的产品数量】:" + num + "\t【库存量】:"
+ list.size() + "\t暂时不能执行生产任务!"); try {
list.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
} //消费条件满足,开始消费
for(int i=0;i<num;i++){
list.remove();
} System.out.println("【已经消费产品数】:" + num + "\t【现仓储量为】:" + list.size()); list.notifyAll();
}
}
}
- 抽象仓库类
public interface AbstractStorage {
void consume(int num);
void produce(int num);
}
- 生产者
public class Producer extends Thread{
//每次生产的数量
private int num ;
//所属的仓库
public AbstractStorage abstractStorage;
public Producer(AbstractStorage abstractStorage){
this.abstractStorage = abstractStorage;
}
public void setNum(int num){
this.num = num;
}
// 线程run函数
@Override
public void run()
{
produce(num);
}
// 调用仓库Storage的生产函数
public void produce(int num)
{
abstractStorage.produce(num);
}
}
- 消费者
public class Consumer extends Thread{
// 每次消费的产品数量
private int num;
// 所在放置的仓库
private AbstractStorage abstractStorage1;
// 构造函数,设置仓库
public Consumer(AbstractStorage abstractStorage1)
{
this.abstractStorage1 = abstractStorage1;
}
// 线程run函数
public void run()
{
consume(num);
}
// 调用仓库Storage的生产函数
public void consume(int num)
{
abstractStorage1.consume(num);
}
public void setNum(int num){
this.num = num;
}
}
- 测试
public class Test{
public static void main(String[] args) {
// 仓库对象
AbstractStorage abstractStorage = new Storage1();
// 生产者对象
Producer p1 = new Producer(abstractStorage);
Producer p2 = new Producer(abstractStorage);
Producer p3 = new Producer(abstractStorage);
Producer p4 = new Producer(abstractStorage);
Producer p5 = new Producer(abstractStorage);
Producer p6 = new Producer(abstractStorage);
Producer p7 = new Producer(abstractStorage);
// 消费者对象
Consumer c1 = new Consumer(abstractStorage);
Consumer c2 = new Consumer(abstractStorage);
Consumer c3 = new Consumer(abstractStorage);
// 设置生产者产品生产数量
p1.setNum(10);
p2.setNum(10);
p3.setNum(10);
p4.setNum(10);
p5.setNum(10);
p6.setNum(10);
p7.setNum(80);
// 设置消费者产品消费数量
c1.setNum(50);
c2.setNum(20);
c3.setNum(30);
// 线程开始执行
c1.start();
c2.start();
c3.start();
p1.start();
p2.start();
p3.start();
p4.start();
p5.start();
p6.start();
p7.start();
}
}
- 输出
【要消费的产品数量】:50 【库存量】:0 暂时不能执行生产任务!
【要消费的产品数量】:20 【库存量】:0 暂时不能执行生产任务!
【要消费的产品数量】:30 【库存量】:0 暂时不能执行生产任务!
【已经生产产品数】:10 【现仓储量为】:10
【要消费的产品数量】:30 【库存量】:10 暂时不能执行生产任务!
【要消费的产品数量】:20 【库存量】:10 暂时不能执行生产任务!
【要消费的产品数量】:50 【库存量】:10 暂时不能执行生产任务!
【已经生产产品数】:10 【现仓储量为】:20
【已经生产产品数】:10 【现仓储量为】:30
【要消费的产品数量】:50 【库存量】:30 暂时不能执行生产任务!
【已经消费产品数】:20 【现仓储量为】:10
【要消费的产品数量】:30 【库存量】:10 暂时不能执行生产任务!
【已经生产产品数】:10 【现仓储量为】:20
【要消费的产品数量】:50 【库存量】:20 暂时不能执行生产任务!
【要消费的产品数量】:30 【库存量】:20 暂时不能执行生产任务!
【已经生产产品数】:10 【现仓储量为】:30
【已经消费产品数】:30 【现仓储量为】:0
【要消费的产品数量】:50 【库存量】:0 暂时不能执行生产任务!
【已经生产产品数】:10 【现仓储量为】:10
【要消费的产品数量】:50 【库存量】:10 暂时不能执行生产任务!
【已经生产产品数】:80 【现仓储量为】:90
【已经消费产品数】:50 【现仓储量为】:40
Java多线程学习之wait、notify/notifyAll 详解的更多相关文章
- Java多线程学习之Lock与ReentranLock详解
synchronized 是内置锁,而Lock 接口定义的是显示锁,Lock 提供了一种可重入的.可轮询的.定时的以及可中断的锁获取操作. ReenTranLock实现了Lock接口,并提供了与syn ...
- Java多线程编程中Future模式的详解
Java多线程编程中,常用的多线程设计模式包括:Future模式.Master-Worker模式.Guarded Suspeionsion模式.不变模式和生产者-消费者模式等.这篇文章主要讲述Futu ...
- Java多线程编程中Future模式的详解<转>
Java多线程编程中,常用的多线程设计模式包括:Future模式.Master-Worker模式.Guarded Suspeionsion模式.不变模式和生产者-消费者模式等.这篇文章主要讲述Futu ...
- java多线程的wait、notify/notifyAll区别
1.wait().notify/notifyAll() 方法是Object的本地final方法,无法被重写. 2.wait()使当前线程阻塞,前提是 必须先获得锁,一般配合synchronized ...
- java多线程同步以及线程间通信详解&消费者生产者模式&死锁&Thread.join()(多线程编程之二)
本篇我们将讨论以下知识点: 1.线程同步问题的产生 什么是线程同步问题,我们先来看一段卖票系统的代码,然后再分析这个问题: package com.zejian.test; /** * @author ...
- Java多线程(三)—— synchronized关键字详解
一.多线程的同步 1.为什么要引入同步机制 在多线程环境中,可能会有两个甚至更多的线程试图同时访问一个有限的资源.必须对这种潜在资源冲突进行预防. 解决方法:在线程使用一个资源时为其加锁即可. 访问资 ...
- java 多线程中的wait方法的详解
java多线程中的实现方式存在两种: 方式一:使用继承方式 例如: PersonTest extends Thread{ String name; public PersonTest(String n ...
- Java多线程之wait、notify/notifyAll 详解,用wait 和notifyAll 以及synchronized实现阻塞队列,多线程拓展之ReentrantLock与Condition
前言:这几天看了很多关于多线程的知识,分享一波.(但是目前接触的项目还未用到过,最多用过线程池,想看线程池 请看我之前的博客) 关于基本的理论等 参考如下: https://www.cnblogs.c ...
- Java再学习——sleep(), wait(), notify(), notifyAll()
首先一点就是Thread.sleep(long millis)方法是Thread类的静态方法,其他三个wait(), notify()和notifyAll()都是Object类的方法. sleep(l ...
随机推荐
- Are We There Yet? (zoj1745)
Are We There Yet? (ZOJ Problem Set - 1745) Are We There Yet? Time Limit: 2 Seconds Memory L ...
- zoj2818 Root of the Problem 简单数学 开方
Root of the Problem Time Limit: 2 Seconds Memory Limit: 65536 KB Given positive integers B and ...
- C++的socket编程学习
前言 不得不承认作为一个前端开发,仍有一个后台开发的梦.从socket通信开始学习,在工作之余补充学习点相关知识,记录下学习的过程. 服务端 服务器代码如下,在设置listen之后,通过accept获 ...
- 【学习】jquery.placeholder.js让IE浏览器支持html5的placeholder
type为text或password的input,其在实际应用时,往往有一个占位符,类似这样的: 在没有html5前,一般写成value,用js实现交互,文本框获得焦点时,提示文字消失,失去焦点时,文 ...
- 【学习】苹果iPhone safari浏览器样式重置修复按钮圆角bug
iPhone safari浏览器中,input按钮会按苹果的默认UI来渲染,例如,写的按钮明明是这个样的: 但是实际就会是这个样子: 怎么办呢? 为按钮添加:-webkit-appearance: n ...
- Microsoft Offce 使用纪事:oneNote笔记本分区删除
OneNote 笔记本和分区删除 OneNote 目前无法在客户端和本地删除已有的笔记本和分区,只能通过OneDrive才能够从云端删除: step1 step2 step3 后记 由于需要登录One ...
- linux 计划任务(crontab)
每天写一点,总有一天我这条咸鱼能变得更咸 cron服务是一个linux下 的定时执行工具,可以在无需人工干预的情况下运行作业.频率可以划分为 分钟 小时 天 月 周,格式如下: 1.crontab 服 ...
- win10 UWP GET Post
win10 应用应该是要有访问网络,网络现在最多的是使用GET,Post,简单的使用,可以用网络的数据:获得博客的访问量. 在使用网络,我们需要设置Package.appxmanifest 网络请求使 ...
- 无限大地图:lightmap拆分
无缝地图涉及到地形.物件的分块加载,同样,lightmap也需要动态加载.而场景烘焙时,所有物件都是一起烘焙的,那怎么把某些物件指定烘焙到某一张lightmap贴图中?网上找了很久,也没有看到具体的实 ...
- Ubuntu15.04 网站服务器环境搭建,php/html/css等学习环境搭建教程
---恢复内容开始--- 本文部分参考自:http://www.cnblogs.com/emouse/archive/2013/06/07/3124009.html 原文中存在少量错误,已改正. 首先 ...