java多线程之生存者与消费者(Java编程思想)
1.通过wait() 与 Notify实现
package Produce; import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit; class Meal { private final int orderNum; public Meal(int orderNum) {
this.orderNum = orderNum;
} @Override
public String toString() {
return "Meal " + orderNum;
}
} class WaitPerson implements Runnable {
private Restaurant restaurant; public WaitPerson(Restaurant r) {
restaurant = r;
} @Override
public void run() {
try {
while (!Thread.interrupted()) {
synchronized (this) {
while (restaurant.meal == null)
wait(); // 等待chef生产meal
}
System.out.println("Waitperson got " + restaurant.meal);
synchronized (restaurant.chef) {
restaurant.meal = null;
restaurant.chef.notifyAll();// 通知chef继续生产
}
}
} catch (InterruptedException e) {
System.out.println("WaitPerson interrupted");
}
}
} class Chef implements Runnable { private Restaurant restaurant;
private int count = 0; public Chef(Restaurant r) {
restaurant = r;
} @Override
public void run() {
try {
while (!Thread.interrupted()) {
synchronized (this) {
while (restaurant.meal != null)
wait();// 等待meal被拿走
}
if (++count == 10) {
System.out.println("Out of food,closing");
restaurant.exec.shutdownNow();//向每个线程发送Interrupt
return;//如果没有直接return 将多执行了下面的 Order up ,所以一般情况下都要直接return
} System.out.println("Order up! ");
synchronized (restaurant.waitPerson) {
// 对notifyAll()的调用必须先获得waitPerson的锁
restaurant.meal = new Meal(count);
restaurant.waitPerson.notifyAll();
}
TimeUnit.MILLISECONDS.sleep(500);//休眠一下是为了给shutdownNow留出时间
}
} catch (InterruptedException e) {
System.out.println("Chef interrupted");
}
}
} public class Restaurant {
Meal meal;
ExecutorService exec = Executors.newCachedThreadPool();
WaitPerson waitPerson = new WaitPerson(this);
Chef chef = new Chef(this); public Restaurant() {
exec.execute(chef);
exec.execute(waitPerson);
} public static void main(String[] args) {
new Restaurant();
}
}
2.使用java.util.concurrent.locks.Condition进行同步操作
Lock和Condition对象只有在更加困难的多线程问题中才是必需的。
package Produce; import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock; class Car {
private Lock lock = new ReentrantLock();
private Condition condition = lock.newCondition();
private boolean waxOn = false; public void waxed() {
lock.lock();
try {
waxOn = true;// Ready to buff
condition.signalAll();
} finally {
lock.unlock();
}
} public void buffed() {
lock.lock();
try {
waxOn = false;// Ready for another coat of wax
condition.signalAll();
} finally {
lock.unlock();
}
} public void waitForWaxing() throws InterruptedException {
lock.lock();
try {
while (waxOn == false)
condition.await();
} finally {
lock.unlock();
}
} public void waitForBuffing() throws InterruptedException {
lock.lock();
try {
while (waxOn == true)
condition.await();
} finally {
lock.unlock();
}
}
} class WaxOn implements Runnable {
private Car car; public WaxOn(Car c) {
car = c;
} @Override
public void run() {
try {
while (!Thread.interrupted())
// while (true) //与使用这行效果一样
{
System.out.println("Wax On!");
TimeUnit.MILLISECONDS.sleep(200);
car.waxed();
car.waitForBuffing();
}
} catch (InterruptedException e) {
System.out.println("Exiting via interrupt");
}
System.out.println("Ending Wax On task");
}
} class WaxOff implements Runnable {
private Car car; public WaxOff(Car c) {
car = c;
} @Override
public void run() {
try {
while (!Thread.interrupted())
// while (true) {
car.waitForWaxing();
System.out.println("Wax Off!");
TimeUnit.MILLISECONDS.sleep(200);
car.buffed();
}
} catch (InterruptedException e) {
System.out.println("Exiting via interrupt");
}
System.out.println("Ending Wax Off task");
}
} public class WaxOMatic2 {
public static void main(String[] args) throws InterruptedException {
Car car = new Car();
ExecutorService exec = Executors.newCachedThreadPool();
exec.execute(new WaxOff(car));
exec.execute(new WaxOn(car));
TimeUnit.SECONDS.sleep(5);
exec.shutdownNow();
}
}
3.通过同步队列实现
package Produce; public class LiftOff implements Runnable {
protected int countDown = 10;
private static int taskCount = 0;
private final int id = taskCount++; public LiftOff() {
} public LiftOff(int countDown) {
this.countDown = countDown;
} public String status() {
return "#" + id + "(" + (countDown > 0 ? countDown : "Liftoff!")
+ ")";
} @Override
public void run() {
while (countDown-- > 0) {
System.out.println(status());
Thread.yield();//线程的礼让
}
} }
package Produce; import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.LinkedBlockingDeque;
import java.util.concurrent.SynchronousQueue; class LiftOffRunner implements Runnable {
private BlockingQueue<LiftOff> rockets; public LiftOffRunner(BlockingQueue<LiftOff> queue) {
rockets = queue;
} public void add(LiftOff lo) {
try {
rockets.put(lo);
} catch (InterruptedException e) {
System.out.println("Interrupted during put()");
}
} @Override
public void run() {
try {
while (!Thread.interrupted()) {
LiftOff rocket = rockets.take();
rocket.run();
}
} catch (InterruptedException e) {
System.out.println("Waking from take()");
}
System.out.println("Exiting LiftOffRunner");
} } public class TestBlockingQueues {
static void getkey() {
try {
// Compensate for Windows/Linux difference in the
// length of the result produced by the Enter key:
new BufferedReader(new InputStreamReader(System.in)).readLine();
} catch (java.io.IOException e) {
throw new RuntimeException(e);
}
} static void getkey(String message) {
System.out.println(message);
getkey();
} static void test(String msg, BlockingQueue<LiftOff> queue) {
System.out.println(msg);
LiftOffRunner runner = new LiftOffRunner(queue);
Thread t = new Thread(runner);
t.start();
for (int i = 0; i < 5; i++) {
runner.add(new LiftOff(5));
}
getkey("Press'Enter'(" + msg + ")");
t.interrupt();
System.out.println("Finished " + msg + " test");
} public static void main(String[] args) {
test("LinkedBlockingQueue", new LinkedBlockingDeque<LiftOff>());// 不限制长度
test("ArrayBlockingQueue", new ArrayBlockingQueue<LiftOff>(3));// 限制长度,当队列满时存数据将阻塞,当队列空时取数据也阻塞
test("SynchronousQueue", new SynchronousQueue<LiftOff>());
} }
4.典型Toast的队列实例
package Produce; import java.util.Random;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.LinkedBlockingDeque;
import java.util.concurrent.TimeUnit; class Toast {
public enum Status {
DRY, BUTTERED, JAMMED
} private Status status = Status.DRY;
private final int id; public Toast(int idn) {
id = idn;
} public void butter() {
status = Status.BUTTERED;
} public void jam() {
status = Status.JAMMED;
} public Status getStatus() {
return status;
} public int getId() {
return id;
} public String toString() {
return "Toast " + id + ": " + status;
}
} class ToastQueue extends LinkedBlockingDeque<Toast> {
} class Toaster implements Runnable {
private ToastQueue toastQueue;
private int count = 0;
private Random rand = new Random(47); public Toaster(ToastQueue tq) {
toastQueue = tq;
} @Override
public void run() {
try {
while (!Thread.interrupted()) {
TimeUnit.MILLISECONDS.sleep(100 + rand.nextInt(500));
Toast t = new Toast(count++);
System.out.println(t);
toastQueue.put(t);
}
} catch (InterruptedException e) {
System.out.println("Toaster interrupted");
}
System.out.println("Toaster off");
}
} class Butterer implements Runnable {
private ToastQueue dryQueue, butteredQueue; public Butterer(ToastQueue dry, ToastQueue buttered) {
dryQueue = dry;
butteredQueue = buttered;
} @Override
public void run() {
try {
while (!Thread.interrupted()) {
// Blocks until next piece of toast is available
Toast t = dryQueue.take();
t.butter();
System.out.println(t);
butteredQueue.put(t);
}
} catch (InterruptedException e) {
System.out.println("Butterer interrupted");
}
System.out.println("Butterer off");
}
} class Jammer implements Runnable {
private ToastQueue butteredQueue, finishedQueue; public Jammer(ToastQueue buttered, ToastQueue finished) {
butteredQueue = buttered;
finishedQueue = finished;
} @Override
public void run() {
try {
while (!Thread.interrupted()) {
Toast t = butteredQueue.take();
t.jam();
System.out.println(t);
finishedQueue.put(t);
}
} catch (InterruptedException e) {
System.out.println("Jammer interrupted");
}
System.out.println("Jammer off");
}
} class Eater implements Runnable {
private ToastQueue finishedqQueue;
private int counter = 0; public Eater(ToastQueue finished) {
finishedqQueue = finished;
} @Override
public void run() {
try {
while (!Thread.interrupted()) {
Toast t = finishedqQueue.take();
if (t.getId() != counter++
|| t.getStatus() != Toast.Status.JAMMED) {
System.out.println(">>>> Error: " + t);
System.exit(1);
} else {
System.out.println("Chomp! " + t);
}
}
} catch (InterruptedException e) {
System.out.println("Eater interrupted");
}
System.out.println("Eater off");
}
} public class ToastOMatic {
public static void main(String[] args) throws Exception {
ToastQueue dryQueue = new ToastQueue(), butteredQueue = new ToastQueue(), finishedQueue = new ToastQueue();
ExecutorService exec = Executors.newCachedThreadPool();
exec.execute(new Toaster(dryQueue));
exec.execute(new Butterer(dryQueue, butteredQueue));
exec.execute(new Jammer(butteredQueue, finishedQueue));
exec.execute(new Eater(finishedQueue));
TimeUnit.SECONDS.sleep(5);
exec.shutdownNow();
} }
5.输入输出管道,功能类似生产者消费者
package Produce; import java.io.IOException;
import java.io.PipedReader;
import java.io.PipedWriter;
import java.util.Random;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit; class Sender implements Runnable {
private Random rand = new Random(47);
private PipedWriter out = new PipedWriter(); public PipedWriter getpPipedWriter() {
return out;
} @Override
public void run() {
try {
while (true) {
for (char c = 'A'; c <= 'z'; c++) {
out.write(c);
TimeUnit.MILLISECONDS.sleep(rand.nextInt(500));
}
}
} catch (IOException e) {
System.out.println(e + " Sender write exception");
} catch (InterruptedException e) {
System.out.println(e + " Sender sleep interrupted");
}
}
} class Receiver implements Runnable {
private PipedReader in; public Receiver(Sender sender) throws IOException {
in = new PipedReader(sender.getpPipedWriter());
} @Override
public void run() {
try {
while (true) {
System.out.println("Read:" + (char) in.read() + ". ");
}
} catch (IOException e) {
System.out.println(e + " Receiver read exception");
}
}
} public class PipedIO {
public static void main(String[] args) throws Exception {
Sender sender = new Sender();
Receiver receiver = new Receiver(sender);
ExecutorService exec = Executors.newCachedThreadPool();
exec.execute(sender);
exec.execute(receiver);
TimeUnit.SECONDS.sleep(4);
exec.shutdownNow();
}
}
java多线程之生存者与消费者(Java编程思想)的更多相关文章
- Java多线程学习(一)Java多线程入门
转载请备注地址:https://blog.csdn.net/qq_34337272/article/details/79640870 系列文章传送门: Java多线程学习(一)Java多线程入门 Ja ...
- Java多线程并发08——锁在Java中的应用
前两篇文章中,为各位带来了,锁的类型及锁在Java中的实现.接下来本文将为各位带来锁在Java中的应用相关知识.关注我的公众号「Java面典」了解更多 Java 相关知识点. 锁在Java中主要应用还 ...
- Java多线程--线程及相关的Java API
Java多线程--线程及相关的Java API 线程与进程 进程是线程的容器,程序是指令.数据的组织形式,进程是程序的实体. 一个进程中可以容纳若干个线程,线程是轻量级的进程,是程序执行的最小单位.我 ...
- Java多线程学习笔记--生产消费者模式
实际开发中,我们经常会接触到生产消费者模型,如:Android的Looper相应handler处理UI操作,Socket通信的响应过程.数据缓冲区在文件读写应用等.强大的模型框架,鉴于本人水平有限目前 ...
- JAVA多线程经典问题 -- 生产者 消费者
工作2年多来一直也没有计划写自己的技术博客,最近辞职在家翻看<thingking in JAVA>,偶尔看到了生产者与消费者的一个经典的多线程同步问题.本人在工作中很少使用到多线程以及高并 ...
- java 多线程 22 :生产者/消费者模式 进阶 利用await()/signal()实现
java多线程15 :wait()和notify() 的生产者/消费者模式 在这一章已经实现了 wait/notify 生产消费模型 利用await()/signal()实现生产者和消费者模型 一样 ...
- Java多线程-并发协作(生产者消费者模型)
对于多线程程序来说,不管任何编程语言,生产者和消费者模型都是最经典的.就像学习每一门编程语言一样,Hello World!都是最经典的例子. 实际上,准确说应该是“生产者-消费者-仓储”模型,离开了仓 ...
- Java多线程学习(七)并发编程中一些问题
本节思维导图: 关注微信公众号:"Java面试通关手册" 回复"Java多线程"获取思维导图源文件和思维导图软件. 多线程就一定好吗?快吗?? 并发编程的目的就 ...
- Java 多线程(六)之Java内存模型
目录 1. 并发编程的两个问题 2 CPU 缓存模型 2.1 CPU 和 主存 2.2 CPU Cache 2.3 CPU如何通过 Cache 与 主内存交互 2.4 CPU 缓存一致性问题 3 Ja ...
随机推荐
- Articles Every Programmer Must Read
http://javarevisited.blogspot.sg/2014/05/10-articles-every-programmer-must-read.html Being a Java pr ...
- JSBinding + SharpKit / 使用 Firefox 调试 JS
已经准备好,google打不开,等打开了再贴图上来
- myBatis 参数配置
关于参数的类型 有四种类型: http://www.07net01.com/zhishi/402787.html 以上链接有所介绍,四种类型有:单个参数.多个参数.Map封装参数.List封装IN 如 ...
- Linq的Distinct方法的扩展
原文地址:如何很好的使用Linq的Distinct方法 Person1: Id=1, Name="Test1" Person2: Id=1, Name="Test1&qu ...
- 024. asp.net中第一次使用GridView (设置鼠标经过时更换背景色)
1. 前端HTML代码 <%@ Page Language="C#" AutoEventWireup="true" CodeFile="Inde ...
- 【转】WinForm不同版本覆盖安装
vs2005为winform程序做的安装包.在以有程序旧版本的机子上用新版本的安装包安装软件时提示 “以经安装该产品的另一个版本.无法继续安装此版本........” 在安装部署项目中设“Remove ...
- pt-heartbeat使用实践
今天无意中看到了沃趣网络科技的一篇文章请不要用SECONDS_BEHIND_MASTER来衡量MYSQL主备的延迟时间感觉分析的相当不错,该文章中也提到了使用pt-heartbeat这个工具检测主从延 ...
- eclipse注解——作者,创建时间,版本
总结: /** * @author liangyadong * @date ${date} ${time} * @version 1.0 */
- Networking in too much detail
The players This document describes the architecture that results from a particular OpenStack config ...
- CXF超时设置
转自: http://peak.iteye.com/blog/1285211 http://win.sy.blog.163.com/blog/static/9419718620131014385644 ...