线程中消费者生产者的实例代码(使用Lock类)
http://www.cnblogs.com/DreamDrive/p/6192685.html 这个是用synchronized关键字实现的.

Lock可以替换synchronized.
上面用来做为锁对象的SaleWindow.class没有别的操作,而且获取锁和释放锁都是在内部隐藏完成的.
Java的思想是万物皆对象,我们把这种锁也描述成为一个对象,就是Lock.....
Lock中的lock和unlock显式的打开和关闭(可视化)更直观.
Lock实现提供了比使用synchronized方法和语句可获得的更广泛的锁定操作.
此实现允许更灵活的结构,可以具有差别很大的属性,可以支持多个相关的Condition对象.
Lock可以替换synchronized.
使用synchronized
synchronized(SaleWindow.class) {
}
SaleWindow.class 这个锁对象没有别的操作,而且这个锁对象获取锁和释放锁的操作都是在内部隐藏的完成的,而Java的思想是万物皆对象.
我们把这种锁也描述成了一个对象,这个对象就是Lock.
Lock中获取锁和释放锁都提供了对应的方法,这两种操作都是一种显式的操作,更直观的表示了这个问题.
如果仅仅把之间的synchronized替换成Lock运行是会报错的.

原因就是锁替换了synchronized 但是wait只能在同步中调用.
我们应该把wait 和 notify 等待唤醒机制都替换掉.
上面说的Condition是将Object监视器方法(wait,notify和notifyAll)分解成截然不同的对象,以便通过这些对象与任意Lock实现组合使用,为每个对象提供多个等待...其中Lock替代了synchronized方法和语句的使用,Condition替代了Object监视器方法的使用.
Condition中有await() signal() 和 signalAll().....

SaleWindow.java
import java.util.List;
import java.util.Random;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock; public class SaleWindow implements Runnable { private List<Food> foods; public List<Food> getFoods() {
return foods;
} public void setFoods(List<Food> foods) {
this.foods = foods;
} public SaleWindow(List<Food> foods) {
this.foods = foods;
} public SaleWindow() {
} public void sale() {
while (true) {
// 加锁
Lock lock = MyLock.LOCK;
Condition cook_con = MyLock.COOK_CON;
Condition sale_con = MyLock.SALE_CON;
lock.lock();
if (foods.size() > 0) {
try {
Food food = foods.get(0);
System.out.println(Thread.currentThread().getName()
+ ": 卖出了 " + food.getId() + " 号饭...");
Random ran = new Random();
int i = ran.nextInt(300); TimeUnit.MILLISECONDS.sleep(i);
foods.remove(0);
// SaleWindow.class.notify();//随机唤醒一条等待的线程
cook_con.signal();
} catch (InterruptedException e) {
e.printStackTrace();
}
} else {
System.out.println(Thread.currentThread().getName()
+ ":饭买完了。厨师赶紧做,我休息了。。。");
try {
sale_con.await();
} catch (InterruptedException e) {
e.printStackTrace();
} }
// 释放锁
lock.unlock();
}
} @Override
public void run() {
sale();
} }
Cook.java
import java.util.List;
import java.util.Random;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock; public class Cook implements Runnable { private List<Food> foods;
private static int num = 1;
private static final int MAXSIZE = 1; public List<Food> getFoods() {
return foods;
} public void setFoods(List<Food> foods) {
this.foods = foods;
} public Cook(List<Food> foods) {
this.foods = foods;
} public Cook() {
} public void produce() {
while (true) {
Lock lock = MyLock.LOCK;
Condition cook_con = MyLock.COOK_CON;
Condition sale_con = MyLock.SALE_CON;
lock.lock();
if (foods.size() < MAXSIZE) {
Food food = new Food((num++) + "");
foods.add(food);
System.out.println(Thread.currentThread().getName() + " :做好 "
+ food.getId() + " 号饭了");
Random ran = new Random();
int i = ran.nextInt(300);
try {
TimeUnit.MILLISECONDS.sleep(i);
} catch (InterruptedException e) {
e.printStackTrace();
} // SaleWindow.class.notify(); sale_con.signal();//唤醒等待中的一条线程
} else {
System.out.println(Thread.currentThread().getName()
+ " :桌子放满了。窗口赶紧卖,我休息了。。。"); try {
cook_con.await();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
lock.unlock();
} } @Override
public void run() {
produce();
}
}
Food.java
public class Food {
private String id;
public Food(String id) {
this.id = id;
}
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
}
MyLock.java
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
//把锁抽取出来.
public class MyLock { public static final Lock LOCK = new ReentrantLock(true);//公平模式
public static final Condition COOK_CON = LOCK.newCondition();//监视Cook的监视器
public static final Condition SALE_CON = LOCK.newCondition();//监视Sale的监视器
//两个监视器之间可以相互通知 本方唤醒对方的等待中的一条线程. //构造方法私有 单例 饿汉式
private MyLock(){}
}
Test.java
import java.util.ArrayList;
import java.util.List; public class Test { public static void main(String[] args) { /*List<Food> foods = new ArrayList<Food>();
for (int i = 0; i < 10; i++) {
foods.add(new Food((i+1)+""));
}
Restaurant r = new Restaurant(foods);
for (int i = 0; i < 3; i++) {
new Thread(r).start();
}*/
List<Food> foods = new ArrayList<Food>();
for (int i = 0; i < 4; i++) {
new Thread(new Cook(foods),"Cook"+(i+1)).start();
}
for (int i = 0; i < 3; i++) {
new Thread(new SaleWindow(foods),"sale"+(i+1)).start();
}
}
}
线程中消费者生产者的实例代码(使用Lock类)的更多相关文章
- 线程中消费者生产者的实例代码(synchronized关键字)
http://www.cnblogs.com/DreamDrive/p/6204665.html 这个是用Lock类实现的. 场景: 厨师类: import java.util.List; impo ...
- Java线程中的join使用实例
JDK中解释为 Waits for this thread to die. 等待本线程结束后,下一个线程才可以运行. 实例要求: 现在有T1.T2.T3三个线程,你怎样保证T2在T1执行完后执行,T3 ...
- Java核心知识点学习----线程中如何创建锁和使用锁 Lock,设计一个缓存系统
理论知识很枯燥,但这些都是基本功,学完可能会忘,但等用的时候,会发觉之前的学习是非常有意义的,学习线程就是这样子的. 1.如何创建锁? Lock lock = new ReentrantLock(); ...
- Java核心知识点 --- 线程中如何创建锁和使用锁 Lock , 设计一个缓存系统
理论知识很枯燥,但这些都是基本功,学完可能会忘,但等用的时候,会发觉之前的学习是非常有意义的,学习线程就是这样子的. 1.如何创建锁? Lock lock = new ReentrantLock(); ...
- 《Lua程序设计》9.2 管道(pipe)与过滤器(filter) 包含使用协同函数实现“生产者——消费者”问题的实例代码
一个关于协同程序的经典示例是“生产者-消费者”问题.这其中涉及到两个函数,一个函数不断地产生值(比如从一个文件中读取值),另一个则不断地消费这些值(比如将这些值写到另一个文件).通常,这两个函数大致是 ...
- 详解 HTML5 中的 WebSocket 及实例代码-做弹幕
原文链接:http://www.php.cn/html5-tutorial-363345.html
- java-多线程的练习----妖,等待唤醒,代码重构,lock到condition
1 需求 资源有姓名和性别. 两个线程, 一个负责给姓名和性别赋值, 一个负责获取姓名和性别的值. 要求1,运行一下,解决程序的 "妖"的问题. 要求2,实现正确数据的 ...
- Python进阶(3)_进程与线程中的lock(线程中互斥锁、递归锁、信号量、Event对象、队列queue)
1.同步锁 (Lock) 当全局资源(counter)被抢占的情况,问题产生的原因就是没有控制多个线程对同一资源的访问,对数据造成破坏,使得线程运行的结果不可预期.这种现象称为“线程不安全”.在开发过 ...
- Java子线程中的异常处理(通用)
在普通的单线程程序中,捕获异常只需要通过try ... catch ... finally ...代码块就可以了.那么,在并发情况下,比如在父线程中启动了子线程,如何正确捕获子线程中的异常,从而进行相 ...
随机推荐
- MFC连接MySQL
其实,以前弄过sql,mysql应该是顺理成章很简单的事情,但很无奈,傻傻地弄了很久,还请教了别人,别人告诉我的跟我在网上查到的都是一样的,但还是不行,归根接地就是“mysql-connector-o ...
- i2c总线,核心,驱动详解
Linux I2C驱动分析(一)----I2C架构和总线驱动 一.I2C总线原理 I2C是一种常用的串行总线,由串行数据线SDA 和串线时钟线SCL组成.I2C是一种多主机控制总线,它和USB总线不同 ...
- JS如何创建对象
js创建对象的方法很多,以下分别介绍
- asp.net DataReader DataTable 使用反射给给实体赋值
asp.net 使用反射给给实体赋值 实体类继承此基类 using System.Reflection; using System.Data.SqlClient; using System.Data; ...
- 2.2.10数据类型String的常量池特性
在JVM中具有String常量池缓存的功能 package com.cky.test; /** * Created by edison on 2017/12/8. */ public class Te ...
- 浅尝辄止之MongoDB
1 简介 MongoDB是一个介于关系数据库和非关系数据库之间的产品,基于分布式文件存储的数据库,旨在为WEB应用提供可扩展的高性能数据存储 解决方案.MongoDB将数据存储为一个文档,数据结构由键 ...
- 14.关键字final
在程序设计中,我们有时可能希望某些数据是不能够改变的,这个时候final就有用武之地了.final是java的关键字,它所表示的是“这部分是无法修改的”.不想被改变的原因有两个:效率.设计.使用到fi ...
- Eclipse新建工作空间,复制原有的配置
步骤一: File->Switch workspace->Other...,按下图选择 只复制简单的配置,如cvs之类的信息是不会复制的. 步骤二: 在方法一的基础上做如下操作 ...
- 用fastreport在进行多列打印时,默认是先行后列,如何改成先列后行排记录?
例子程序中的6.fr3是在Page中设置 columns=2这样就是先行后列,7.fr3就是3列先列后行的例子 1 6 2 7 3 8 4 9 5 10 但如果 ...
- redis -编译、启动、停止
一.下载.编译 redis是以源码方式发行的,先下载源码,然后在linux下编译 1.1 http://www.redis.io/download 先到这里下载Stable稳定版,目前最新版本是2.8 ...