package com.atguigu.thread.lock;

 import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock; /*
* 小米厂家:
* 库房有限,只能存10台小米电视
* 工人的生产电视与销售的卖电视同时进行
* 当工人生产电视把库房存满了,要求工人休息,直到销售卖出至少一台电视,库房可以再次电视,然后他再次开始生产
* 当销售者把库房的电视都卖完了,要求销售者休息,直到工人生产了至少一台电视,销售才继续卖电视
*
* 工人是一个线程
* 销售是一个线程
*
* 需要线程的通信:当工人休息后,销售组销售了电视,应该告知工人一声,可以继续生产了
* 当销售休息后,工人如果生产了电视,应该通知销售,可以开始卖电视了
*
* 问题:
* (1)因为共享num变量,所以有线程安全问题:依靠同步解决
* (2)因为库房有限:线程通信 wait,notify
*
* 涉及到的方法:
* (1)wait:等待
* (2)notify/notifyAll:通知
*
* 这两个方法必须由“锁”对象来调用
* “锁”对象,必须是多个线程共享的锁对象
*
* 如果是多个工人,多个销售者
*
* synchronized:隐式锁
* wait
* notify/notifyAll
*
* 如果使用Lock锁,那么线程通信应该使用Condition来解决通信
* 条件.await():某种条件,等待
* 条件.signal():某种条件唤醒
*
*/
public class TestTongXin { public static void main(String[] args) {
Houseware h = new Houseware(); Worker w1 = new Worker(h);
Worker w2 = new Worker(h);
Saler s1 = new Saler(h);
Saler s2 = new Saler(h); w1.start();
w2.start();
s1.start();
s2.start();
} }
class Houseware{
private static final int MAX_VALUE = 10;
private int num = 0;
private Lock lock = new ReentrantLock();
private Condition full = lock.newCondition();
private Condition empty = lock.newCondition(); //往里放电视
public void add(){
lock.lock();
if(num>=MAX_VALUE){
try {
full.await();
} catch (InterruptedException e) {
e.printStackTrace();
}
}else{
num++;
try {
Thread.sleep(100);//为了问题暴露的明显一点
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("工人生产了一台电视,现在库存是:" + num);
// empty.signal();
empty.signalAll();
} lock.unlock();
} //往外拿电视
public void take(){
lock.lock();
if(num<=0){
try {
empty.await();
} catch (InterruptedException e) {
e.printStackTrace();
}
}else{
num--;
try {
Thread.sleep(100);//为了问题暴露的明显一点
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("销售卖了一台电视,现在库存是:" + num);
full.signalAll();
} lock.unlock();
}
} class Worker extends Thread{
private Houseware h; public Worker(Houseware h) {
super();
this.h = h;
} public void run(){
//往仓库放电视
// 库房.add();
while(true){
h.add();
}
}
}
class Saler extends Thread{
private Houseware h; public Saler(Houseware h) {
super();
this.h = h;
} public void run(){
while(true){
h.take();
}
}
}

java多线程 生产者和消费者 lock的更多相关文章

  1. Java 多线程-生产者、消费者

    一.整体代码 ThreadDemo.java public class ThreadDemo { public static void main(String[] args) { Godown god ...

  2. JAVA基础再回首(二十五)——Lock锁的使用、死锁问题、多线程生产者和消费者、线程池、匿名内部类使用多线程、定时器、面试题

    JAVA基础再回首(二十五)--Lock锁的使用.死锁问题.多线程生产者和消费者.线程池.匿名内部类使用多线程.定时器.面试题 版权声明:转载必须注明本文转自程序猿杜鹏程的博客:http://blog ...

  3. Windows下RabbitMQ 的下载、配置、Java实现生产者和消费者例子

    RabbitMQ是一个轻量级的消息代理中间件,支持多种消息通信协议,支持分布式部署,支持运行于多个操作系统,具有灵活.高可用等特性.RabbitMQ支持多种协议,其中最为重要的是高级消息队列协议(AM ...

  4. java实现生产者和消费者问题

    Java实现生产者和消费者问题 欢迎访问我的个人博客,获取更多有用的东西 链接一 链接二 也可以关注我的微信订阅号:CN丶Moti

  5. Java中生产者与消费者模式

    生产者消费者模式 首先来了解什么是生产者消费者模式.该模式也称有限缓冲问题(英语:Bounded-buffer problem),是一个多线程同步问题的经典案例.该问题描述了两个共享固定大小缓冲区的线 ...

  6. Java实现生产者和消费者

    生产者和消费者问题是操作系统的经典问题,在实际工作中也常会用到,主要的难点在于协调生产者和消费者,因为生产者的个数和消费者的个数不确定,而生产者的生成速度与消费者的消费速度也不一样,同时还要实现生产者 ...

  7. python多线程+生产者和消费者模型+queue使用

    多线程简介 多线程:在一个进程内部,要同时干很多事情,就需要同时执行多个子任务,我们把进程内的这些子任务叫线程. 线程的内存空间是共享的,每个线程都共享同一个进程的资源 模块: 1._thread模块 ...

  8. java之生产者与消费者

    package com.produce; import java.util.LinkedList; import java.util.Queue; /*@author shijin * 生产者与消费者 ...

  9. java线 生产者和消费者

    watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvbGlhbmdydWkxOTg4/font/5a6L5L2T/fontsize/400/fill/I0JBQk ...

随机推荐

  1. 可能是史上最全的机器学习和Python(包括数学)速查表

    新手学习机器学习很难,就是收集资料也很费劲.所幸Robbie Allen从不同来源收集了目前最全的有关机器学习.Python和相关数学知识的速查表大全.强烈建议收藏! 机器学习有很多方面. 当我开始刷 ...

  2. 写个批处理脚本来帮忙干活--遍历文件夹&字符串处理

    这次打算写几篇关于脚本方面的博客,主要是记录一下 Gradle 脚本和批处理脚本的一些写法,方便后续查阅. 前言 平常开发过程中,一些较为重复的手工性工作,如果能让脚本来帮忙处理,自然是最好的,刚好之 ...

  3. springboot集成schedule(深度理解)

    背景 在项目开发过程中,我们经常需要执行具有周期性的任务.通过定时任务可以很好的帮助我们实现. 我们拿常用的几种定时任务框架做一个比较: 从以上表格可以看出,Spring Schedule框架功能完善 ...

  4. python实现邮件的发送

    一.163邮箱设置 进入163邮箱,点击设置中的pop3/smtp/imap 开启smtp服务,如果没有开启,点击设置,手机号验证后勾选开启即可,开启后图如下: 主要用到的就是smtp服务器:smtp ...

  5. Javascript高级程序设计复习——第五章引用类型 【原创】

    5.1  Object类型 1:创建Object实例的两种方式 ①new构造法 var obj1 = new Object(); 注意大写!不传递参数时可以省略圆括号 obj1.hehe = &quo ...

  6. angularJS---自定义过滤器

    AngularJS另一个特点就是提供了过滤器,可以通过操作UNIX下管道的方式,操作数据结果. 通过使用管道,可以便于双向的数据绑定中视图的展现. 过滤器在处理过程中,将数据变成新的格式,而且可以使用 ...

  7. linux下如何配置yum源

    first:挂载本地镜像文件(挂载:意为将某个文件放置在系统的一个目录下) mkdir     /media/cdrom  #新建镜像文件挂载目录 cd         /usr/local/src  ...

  8. monitor.go 源码阅读

    package main import (     "fmt"     "net/http" ) // 查询监控信息的接口 func statsHandler( ...

  9. nsq源码阅读笔记之nsqd(四)——Channel

    与Channel相关的代码主要位于nsqd/channel.go, nsqd/nsqd.go中. Channel与Topic的关系 Channel是消费者订阅特定Topic的一种抽象.对于发往Topi ...

  10. Executor框架简介

    Executor框架是在Java5中引入的,可以通过该框架来控制线程的启动,执行,关闭,简化并发编程.Executor框架把任务提交和执行解耦,要执行任务的人只需要把任务描述清楚提交即可,任务的执行提 ...