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 ...
随机推荐
- set and Sequence theory
https://en.wikipedia.org/wiki/Class_(set_theory) https://en.wikipedia.org/wiki/Zermelo%E2%80%93Fraen ...
- MySQL : interactive_timeout v/s wait_timeout
Most of the database intensive applications are worring about the default values of these variables ...
- 011. asp.net内置对象
Response对象: Response代表了服务器响应对象, 主要用于将数据从服务器发送回浏览器; 每次客户端发出一个请求的时候,服务器就会用一个响应对象来处理这个请求,处理完这个请求之后,服务器就 ...
- 渲染voronoi图
渲染voronoi图要比计算voronoi图简单. 渲染voronoi图: 方法1: 在pixel shader里,对每一个像素,求哪个种子点到它的距离最近,将此种子点的颜色作为此像素颜色. 当种子点 ...
- docker nodejs 基本应用
1. 安装docker 环境 2. nodejs 应用布局 package.json { "name": "docker-centos-hello", &qu ...
- android 旋转手机的时候,如何忽略onCreate再次被系统调用?
实现一个程序,主要是不想在手机横竖屏的时候重新onCreate,所以在配置文件中增加了配置选项: android:configChanges="orientation|keyboardHid ...
- Java模板引擎 HTTL
新一代java模板引擎典范 Beetl http://www.oschina.net/p/httl HTTL(Hyper-Text Template Language)是一个高性能的开源JAVA模板引 ...
- 持续集成之Jenkins(坏老头)
点击关注哦↑↑↑↑↑↑↑↑↑ 持续集成 有关持续集成的简介,可参考我此前的文章:http://blog.csdn.net/benkaoya/article/details/44993583 Jenki ...
- nginx path_info问题解决
问题: 访问www.xxxx.com/index.php/api/xxxxxxxxx网址时,提示无法访问,找不到页面 解决: 第一次,是改了nginx.conf,不会报这个错误了,但还是没有用 loc ...
- innertext与innerhtml
<div id="test"> <span style="color:red">test1</span> test2 < ...