说明

  • Object.wait()使当前的线程进入到等待状态(进入到等待队列)
  • Object.notifyAll() 唤醒等待中的全部线程
  • Object.notify() 随机唤醒一个线程

代码

consumer.java

public class Consumer extends Thread {
List<Object> container;
/*表示当前线程共生产了多少件物品*/
private int count; public Consumer(String name, List<Object> container) {
super(name);
this.container = container;
} @Override
public void run() { while(true){
synchronized (container) {
try {
if (container.isEmpty()) { //仓库已空,不能消 只能等
container.wait(20); } else {
// 消费
container.remove(0);
this.count++;
System.out.println("消费者:" + getName() + " 共消费了:" + this.count + "件物品,当前仓库里还有" + container.size() + "件物品");
container.notifyAll(); // 唤醒等待队列中所有线程
} } catch (InterruptedException e) {
e.printStackTrace();
}
} try {
sleep(10);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}

Producer.java

public class Producer extends Thread{

    List<Object> container;
/*表示当前线程共生产了多少件物品*/
private int count; public Producer(String name, List<Object> container) {
super(name);
this.container = container;
} @Override
public void run() {
while (true) {
synchronized (container) {
try {
// 如果某一个生产者能执行进来,说明此线程具有container对象的控制权,其它线程(生产者&消费者)都必须等待
if (container.size() == 10) { // 假设container最多只能放10个物品,即仓库已满
container.wait(10); //表示当前线程需要在container上进行等待
} else {
// 仓库没满,可以放物品
container.add(new Object());
this.count++;
System.out.println("生产者:" + getName() + " 共生产了:" + this.count + "件物品,当前仓库里还有" + container.size() + "件物品");
// 生产者生产了物品后应通知(唤醒)所有在container上进行等待的线程(生产者&消费者)
// 生:5, 消:5
// container.notify(); // 随机唤醒一个在等待队列中的线程
container.notifyAll(); // 唤醒等待队列中所有线程
}
} catch (InterruptedException e) {
e.printStackTrace();
}
} // try {
sleep(20);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}

Test.java

public class Test {

    public static void main(String[] args) {
// 仓库
List<Object> container = new ArrayList<>(); new Producer("老王", container).start();
new Consumer("小芳", container).start();
new Producer("老李", container).start();
new Consumer("小荷", container).start();
new Producer("老张", container).start(); new Consumer("小花", container).start();
new Producer("老刘", container).start();
new Consumer("小妞", container).start();
new Consumer("小米", container).start();
new Producer("老马", container).start(); }
}

Java 学习笔记 使用synchronized实现生产者消费者模式的更多相关文章

  1. Java Thread系列(十)生产者消费者模式

    Java Thread系列(十)生产者消费者模式 生产者消费者问题(producer-consumer problem),是一个多线程同步问题的经典案例.该问题描述了两个共亨固定大小缓冲区的线程-即所 ...

  2. java ReentrantLock结合条件队列 实现生产者-消费者模式 以及ReentratLock和Synchronized对比

    package reentrantlock; import java.util.ArrayList; public class ProviderAndConsumerTest { static Pro ...

  3. python 多线程笔记(6)-- 生产者/消费者模式(续)

    用 threading.Event() 也可以实现生产者/消费者模式 (自己拍脑袋想出来的,无法知道其正确性,请大神告知为谢!) import threading import time import ...

  4. Java的设计模式(7)— 生产者-消费者模式

    生产者-消费者模式是一个经典的多线程设计模式,它为多线程间的协作提供了良好的解决方案.这个模式中,通常有两类线程,即若干个生产者线程和若干个消费者线程.生产者线程负责提交用户请求,消费者线程则负责具体 ...

  5. python 多线程笔记(5)-- 生产者/消费者模式

    我们已经知道,对公共资源进行互斥访问,可以使用Lock上锁,或者使用RLock去重入锁. 但是这些都只是方便于处理简单的同步现象,我们甚至还不能很合理的去解决使用Lock锁带来的死锁问题. 要解决更复 ...

  6. Java笔记1 : 在生产者消费者模式中,线程通信与共享数据,死锁问题与解决办法

    本例定义了4个类,这里说一下,方便下面讲解.分别是Product(产品),Producer(生产者),Consumer(消费者), Test(测试类). 多线程之间通信与共享数据只要引用同一内存区域就 ...

  7. 2.3多线程(java学习笔记)synchronized关键字

    一.为什么要用synchronized关键字 首先多线程中多个线程运行面临共享数据同步的问题. 多线程正常使用共享数据时需要经过以下步骤: 1.线程A从共享数据区中复制出数据副本,然后处理. 2.线程 ...

  8. Java 学习笔记之 Synchronized锁重入

    Synchronized锁重入: 当一个线程得到一个对象锁后,再次请求此对象锁时是可以再次得到该对象的锁.这也证明在一个Synchronized方法/块的内部调用本类的其他Synchronized方法 ...

  9. Java 学习笔记之 Synchronized锁对象

    Synchronized锁对象: Synchronized取得的锁都是对象锁,而不是把一段代码或方法当作锁,哪个线程执行带synchronized关键字的方法,哪个线程就持有该方法所属对象的锁,那么其 ...

随机推荐

  1. Oracle报错ORA-12516 TNS:listener could not find available handler with matching protocol stack

    解决办法定位原因-- 以sysdba身份登陆PL/SQL sqlplus / as sysdba;-- 查看当前连接进程数SQL>select count(*) from v$process;- ...

  2. Java-JSON 解析

    JSON  JSON(JavaScript Object Notation, JS 对象简谱) 是一种轻量级的数据交换格式.它基于 ECMAScript (欧洲计算机协会制定的js规范)的一个子集,采 ...

  3. git 服务器搭建与运用

    环境:CentOS 6 为了不影响后面的安装 安装依赖库 yum install curl-devel expat-devel gettext-devel openssl-devel zlib-dev ...

  4. linux 重新生成网卡配置文件

    nmcli connection add con-name home type ethernet ifname eth1 autoconnect yes ip4 10.1.252.60/24 gw4 ...

  5. Ajax验证用户名是否被注册

    Ajax验证用户名是否被注册 var xmlHttp; function createXMLHttpRequest(){ // 创建XMLHttp请求对象 if(window.ActiveXObjec ...

  6. Task 的用法

    Task的功能喝Thread类似,写法也很简单: 两种方式: 第一 Task t1=new Task(()=>{}); t1.Start();//启动Task t1.Wait();//若调用Wa ...

  7. js操作DOM对象

    js操作DOM对象  (Document Object Model)文档对象模型 nodeType返回值 1:元素节点 2:属性节点 3:文本节点 8:注释节点 9: 文档节点 nodeName 节点 ...

  8. [Swift]LeetCode50. Pow(x, n) | Pow(x, n)

    Implement pow(x, n), which calculates x raised to the power n (xn). Example 1: Input: 2.00000, 10 Ou ...

  9. [Swift]LeetCode155. 最小栈 | Min Stack

    Design a stack that supports push, pop, top, and retrieving the minimum element in constant time. pu ...

  10. [Swift]LeetCode897. 递增顺序查找树 | Increasing Order Search Tree

    Given a tree, rearrange the tree in in-order so that the leftmost node in the tree is now the root o ...