说明

  • 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. nodejs内存溢出

    npm-v 报错,错误信息如下: FATAL ERROR: Ineffective mark-compacts near heap limit Allocation failed - JavaScri ...

  2. ThinkPHP5 打开多语言支持

    1.在thinkphp\start.php 页面中添加多语言的切换函数的参数格式,本贴目前只支持两种语言,并注意必须全部小写!全部小写!!全部小写!!!,注意这一步很关键 Lang::setAllow ...

  3. 算法与数据结构(三) 二叉树的遍历及其线索化(Swift版)

    前面两篇博客介绍了线性表的顺序存储与链式存储以及对应的操作,并且还聊了栈与队列的相关内容.本篇博客我们就继续聊数据结构的相关东西,并且所涉及的相关Demo依然使用面向对象语言Swift来表示.本篇博客 ...

  4. Linux atop监控

    200 ? "200px" : this.width)!important;} --> 介绍 atop是一个功能非常强大的linux服务器监控工具,它的数据采集主要包括:CP ...

  5. 【RL-TCPnet网络教程】第30章 RL-TCPnet之SNTP网络时间获取

    第30章      RL-TCPnet之SNTP网络时间获取 本章节为大家讲解RL-TCPnet的SNTP应用,学习本章节前,务必要优先学习第29章的NTP基础知识.有了这些基础知识之后,再搞本章节会 ...

  6. 多媒体文件格式(一):MP4 格式

    在互联网常见的格式中,跨平台最好的应该就属MP4文件了.因为MP4文件既可以在PC平台的Flashplayer中播放,又可以在移动平台的Android.iOS等平台中进行播放,而且使用系统默认的播放器 ...

  7. Javascript高级编程学习笔记(88)—— Canvas(5)绘制文本

    绘制文本 同样的,canvas也为绘制文本提供了相应的方法. 2D上下文提供的文本绘制方法主要有两个: fillText() strokeText() 这两个方法都接受四个参数 要绘制的文本字符串 绘 ...

  8. BBS论坛(十六)

    16.登录功能完成 (1)front/forms.py class SigninForm(BaseForm): telephone = StringField(validators=[Regexp(r ...

  9. Docker 下载镜像

    文章首发个人网站: https://www.exception.site/docker/docker-pull-image 本文中,我们将需要学习 Docker 如何下载镜像? 一.前言 大家都知道, ...

  10. json对象和json字符串

    Javascript字符串与JSON字符串的最大区别在于,JSON字符串必须使用双引号(单引号会导致语法错误) 与Javascript的对象字面量相比,JSON对象有两个地方不一样.首先,没有声明变量 ...