线程中消费者生产者的实例代码(使用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 ...代码块就可以了.那么,在并发情况下,比如在父线程中启动了子线程,如何正确捕获子线程中的异常,从而进行相 ...
随机推荐
- Linux下通过管道杀死所有与tomcat相关的进程
先将正确的命令放上来: ps -ef | grep ps -ef将系统中运行的进程展示出来 选择带有tomcat的进程后同时去除自身带有grep的进程,毕竟本身运行的这条命令是与tomcat相关的 a ...
- AngularJS的select设置默认值
AngularJS的select设置默认值 在使用Angular时候使用select标签时会遇到绑定数据指定默认显示值可这样实现 <!DOCTYPE html> <html ng-a ...
- redis-server进程CPU百分百问题
结论:待确认是否为redis的BUG,原因是进程实际占用的内存远小于配置的最大内存,所以不会是内存不够需要淘汰.CPU百分百redis-server进程集群状态:slave临时解决办法:使用gdb将d ...
- MFC载入BMP图片
两步 hBitmap = (HBITMAP)LoadImage(NULL,fullPathName,IMAGE_BITMAP,120,120,LR_LOADFROMFILE);//载入图片 m_pic ...
- inline-block 引发的间隙原因与解决方法
这是一个常见的问题,但是一些新人没遇到过可能不会发现,现在我对这种现在进行了分析与总结 设置一些元素为块级元素时一般这么写 li{display:inline-block; *display:inli ...
- day24(JAVAWEB上传与下载)
javaWeb上传与下载 上传: 上传方式: jspSmartUpload :应用在jsp上的文件上传与下载组件. FileUpload :用用在jaava环境上的上传的功能 ...
- 20169207《Linux内核原理与分析》第十周作业
这周除了阅读学习教材「Linux内核设计与实现 (Linux Kernel Development)」第教材第15,16章外.我们还需要接着完成学习MOOC「Linux内核分析」第八讲「Linux系统 ...
- Android开发——利用Cursor+CursorAdapter实现界面实时更新
好久没有更新博客了.不是没时间写,而是太懒.而且感觉有些东西没有时间总结,之之后再想写,就想不起来了.晚上新发现一点东西,所以就及时写下来. 最近利用业余时间在看Android的Download模块, ...
- android 发送url带中文出现乱码怎么解决
上传的时候参数中带中文的时候发送参数的时候就有可能出现乱码,这种情况怎么解决呢,就是设置url的格式为utf-8 httpRequest.setEntity(new UrlEncodedFormEnt ...
- UIKit-UIBezierPath
UIBezierPath精讲 http://www.henishuo.com/uibezierpath-draw/ iOS UIBezierPath类 介绍 http://justsee.iteye. ...