生产者消费者

1.
class Meal {
private final int orderNum;

public Meal(int orderNum) {
this.orderNum = orderNum;
}

public String toString() {
return "Meal " + orderNum;
}
}

class WaitPerson implements Runnable {
private Restaurant restaurant;

public WaitPerson(Restaurant r) {
restaurant = r;
}

public void run() {
try {
while (!Thread.interrupted()) {
synchronized (this) {
while (restaurant.meal == null)
wait(); // ... for the chef to produce a meal
}
System.out.println("Waitperson got " + restaurant.meal);
synchronized (restaurant.chef) {
restaurant.meal = null;
restaurant.chef.notifyAll(); // Ready for another
}
}
} 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;
}

public void run() {
try {
while (!Thread.interrupted()) {
synchronized (this) {
while (restaurant.meal != null)
wait(); // ... for the meal to be taken
}
if (++count == 10) {
System.out.println("Out of food, closing");
restaurant.exec.shutdownNow();
}
System.out.println("Order up! ");
synchronized (restaurant.waitPerson) {
restaurant.meal = new Meal(count);
restaurant.waitPerson.notifyAll();
}
TimeUnit.MILLISECONDS.sleep(100);
}
} 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();
}
}

注意点:
(1).注意同步this是同步哪个对象
(2).exec.shutdownNow()当调用这个方法的时候,将会向所有由它启动的任务发生interrupt,当线程接受到中断时,并不会立即中断,而是遇到可中断方法时才中断,比如sleep。


2.java.util.concurrent.locks.Condition类的用法:
没有Condition的时,如下:

import java.util.concurrent.*;

class Car {
private boolean waxOn = false;

public synchronized void waxed() {
waxOn = true; // Ready to buff
notifyAll();
}

public synchronized void buffed() {
waxOn = false; // Ready for another coat of wax
notifyAll();
}

public synchronized void waitForWaxing() throws InterruptedException {
while (waxOn == false)
wait();
}

public synchronized void waitForBuffing() throws InterruptedException {
while (waxOn == true)
wait();
}
}

class WaxOn implements Runnable {
private Car car;

public WaxOn(Car c) {
car = c;
}

public void run() {
try {
// while (!Thread.interrupted()) {
for(int i=0;i<2;i++){
System.out.println("in on"+i);
System.out.println("Wax On! ");
TimeUnit.MILLISECONDS.sleep(200);
car.waxed();
car.waitForBuffing();
System.out.println("out on"+i);
}

// }
} 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;
}

public void run() {
try {
// while (!Thread.interrupted()) {
for(int i=0;i<2;i++){

System.out.println("in off"+i);
TimeUnit.MILLISECONDS.sleep(1000);
car.waitForWaxing();
System.out.println("Wax Off! ");
car.buffed();
System.out.println("out off"+i);
}
// }
} catch (InterruptedException e) {
System.out.println("Exiting via interrupt");
}
System.out.println("Ending Wax Off task");
}
}

public class WaxOMatic {
public static void main(String[] args) throws Exception {
Car car = new Car();
ExecutorService exec = Executors.newCachedThreadPool();
exec.execute(new WaxOff(car));
exec.execute(new WaxOn(car));
TimeUnit.SECONDS.sleep(5); // Run for a while...
exec.shutdownNow(); // Interrupt all tasks
}
}

注意:当调用notifyAll时,如果没有没有任何线程挂起,将会忽略

使用condition之后:
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;
}

public void run() {
try {
while (!Thread.interrupted()) {
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;
}

public void run() {
try {
while (!Thread.interrupted()) {
TimeUnit.MILLISECONDS.sleep(1000);
car.waitForWaxing();
System.out.println("Wax Off! ");
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 Exception {
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.生产者消费者队列
wait和notifyAll方法以一种非常低效的方式解决了任务互操作问题,即每次交互都需要握手。我们可以使用同步队列来解决任务协作问题,同步队列在任何时候都只允许一个任务插入或异常元素。如果消费者试图从队列中获取对象,而改队列此时为空,那么队列还可以挂起消费者任务,当有内容时再恢复消费者任务。例如:

class LiftOffRunner implements Runnable {
BlockingQueue<LiftOff> rockets;

public LiftOffRunner(BlockingQueue<LiftOff> queue) {
rockets = queue;
}

public void add(LiftOff lo) {
try {
System.out.println("前:"+rockets.size());
rockets.put(lo);
System.out.println("后:"+rockets.size());
} catch (InterruptedException e) {
System.out.println("Interrupted during put()");
}
}

public void run() {
try {
while (!Thread.interrupted()) {
LiftOff rocket = rockets.take();
rocket.run(); // Use this thread
}
} 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++){
System.out.println(":"+runner.rockets.size());
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", // Unlimited size
new LinkedBlockingQueue<LiftOff>());
//大小限制固定值,当添加元素时,如果队列已经满,那将会挂起,等有元素取走时,再添加
test("ArrayBlockingQueue", // Fixed size
new ArrayBlockingQueue<LiftOff>(3));
//大小限制固定值为1,当添加1个元素,而没有取走时,将会挂起,等取走后,再恢复
test("SynchronousQueue", // Size of 1
new SynchronousQueue<LiftOff>());
}
}


更好的一个例子:先生产土司、然后涂黄油、最后涂果酱

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 LinkedBlockingQueue<Toast> {}

class Toaster implements Runnable {
private ToastQueue toastQueue;
private int count = 0;
private Random rand = new Random(47);
public Toaster(ToastQueue tq) { toastQueue = tq; }
public void run() {
try {
while(!Thread.interrupted()) {
TimeUnit.MILLISECONDS.sleep(
100 + rand.nextInt(500));
// Make toast
Toast t = new Toast(count++);
System.out.println(t);
// Insert into queue
toastQueue.put(t);
}
} catch(InterruptedException e) {
System.out.println("Toaster interrupted");
}
System.out.println("Toaster off");
}
}

// Apply butter to toast:
class Butterer implements Runnable {
private ToastQueue dryQueue, butteredQueue;
public Butterer(ToastQueue dry, ToastQueue buttered) {
dryQueue = dry;
butteredQueue = buttered;
}
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");
}
}

// Apply jam to buttered toast:
class Jammer implements Runnable {
private ToastQueue butteredQueue, finishedQueue;
public Jammer(ToastQueue buttered, ToastQueue finished) {
butteredQueue = buttered;
finishedQueue = finished;
}
public void run() {
try {
while(!Thread.interrupted()) {
// Blocks until next piece of toast is available:
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");
}
}

// Consume the toast:
class Eater implements Runnable {
private ToastQueue finishedQueue;
private int counter = 0;
public Eater(ToastQueue finished) {
finishedQueue = finished;
}
public void run() {
try {
while(!Thread.interrupted()) {
// Blocks until next piece of toast is available:
Toast t = finishedQueue.take();
// Verify that the toast is coming in order,
// and that all pieces are getting jammed:
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();
}
}

4.在输入输出问题上,也可以使用类似的可自动挂起和恢复的类pipedWriter和pipedReader类,例如:

class Sender implements Runnable {
private Random rand = new Random(47);
private PipedWriter out = new PipedWriter();

public PipedWriter getPipedWriter() {
return out;
}

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.getPipedWriter());
}

public void run() {
try {
while (true) {
// Blocks until characters are there:
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();
}
}

但是和同步队列比起来,还是同步队列更加健壮,而且容易使用。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值