并发编程(三)-线程协作

来源:互联网 发布:知乎的用户数量 编辑:程序博客网 时间:2024/06/10 20:33
线程协作指多个线程之间协调地交替执行,线程协作有两种方式:
1.wait/notify,notifyAll
该方法需要搭配synchronized关键字使用,wait(),notify(),notifyAll()必须在同步方法或者同步块中使用,否则会抛出IllegalMonitorStateException异常.注意notify(),notifyAll()只能唤醒在同一锁对象上的wait()线程.

下面是生产者或消费者的例子

public class Restaurant {public Meal meal;public Customer customer=new Customer(this);public Chef chef=new Chef(this);public ExecutorService exec=Executors.newCachedThreadPool();public Restaurant(){exec.execute(customer);exec.execute(chef);}public static void main(String[] args) {new Restaurant();}}class Meal{private final int orderNum;public Meal(int orderNum){this.orderNum=orderNum;}public String toString(){ return "Meal "+orderNum;}}class Customer implements Runnable{private Restaurant rest;public Customer(Restaurant rest){this.rest=rest;}public void run(){try{while(!Thread.interrupted()){synchronized(this){while(rest.meal==null){wait();}System.out.println("customer got "+rest.meal);}synchronized(rest.chef){rest.meal=null;rest.chef.notify();}}}catch(InterruptedException ex){System.out.println("customer interrupted");}}}class Chef implements Runnable{private Restaurant rest;private int count=0;public Chef(Restaurant rest){this.rest=rest;}public void run(){try{while(!Thread.interrupted()){synchronized(this){while(rest.meal!=null){wait();}}if(count++==10){System.out.println("Out of Food!");rest.exec.shutdownNow();}System.out.println("order up!");synchronized(rest.customer){rest.meal=new Meal(count);rest.customer.notify();}TimeUnit.MILLISECONDS.sleep(100);}}catch(InterruptedException e){System.out.println("chef interrupted");}}}输出:order up!customer got Meal 1order up!customer got Meal 2order up!customer got Meal 3order up!customer got Meal 4order up!customer got Meal 5order up!customer got Meal 6order up!customer got Meal 7order up!customer got Meal 8order up!customer got Meal 9order up!customer got Meal 10Out of Food!order up!customer interruptedchef interrupted
2.condition.await(),condition.signal(),condition.signalAll()
需要搭配Lock进行使用,使用起来更加复杂;使用condition实现生产者和消费者的例子,注意signal()signalAll()只能唤醒同一个lock下,同一个condition上的await()线程;可以看到,使用condition实现更加复杂
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;public class Restaurant {Meal meal;Customer customer=new Customer(this);Chef chef=new Chef(this);ExecutorService exec=Executors.newCachedThreadPool();public Restaurant(){exec.execute(customer);exec.execute(chef);}public static void main(String[] args) {new Restaurant();}}class Meal{private int orderNum;public Meal(int orderNum){this.orderNum=orderNum;}public String toString(){return "Meal "+orderNum;}}class Customer implements Runnable{Restaurant rest;public Customer(Restaurant rest){this.rest=rest;}public Lock lock=new ReentrantLock();public Condition condition=lock.newCondition();public void run(){try{while(!Thread.interrupted()){lock.lock();try{while(rest.meal==null){condition.await();}}finally{lock.unlock();}System.out.println("Customer get "+rest.meal);rest.meal=null;rest.chef.lock.lock();try{rest.chef.condition.signalAll();}finally{rest.chef.lock.unlock();}}}catch(InterruptedException ex){System.out.println("Customer is interrupted!");}}}class Chef implements Runnable{Restaurant rest;public Chef(Restaurant rest){this.rest=rest;}public Lock lock=new ReentrantLock();public Condition condition=lock.newCondition();private int count=0;public void run(){try{while(!Thread.interrupted()){lock.lock();try{while(rest.meal!=null){condition.await();}}finally{lock.unlock();}if(++count==10){System.out.println("out of food!");rest.exec.shutdownNow();}rest.meal=new Meal(count);rest.customer.lock.lock();try{rest.customer.condition.signalAll();}finally{rest.customer.lock.unlock();}System.out.println("Order up!");TimeUnit.MILLISECONDS.sleep(300);}}catch(InterruptedException ex){System.out.println("Chef is interrupted!");}}}
3.BlockingQueue<T>
常用的BlockQueue接口实现由ArrayBlockQueue和LinkedBlockingQueue,以下使用容量为1的LinkedBlockQueue实现

import java.util.concurrent.BlockingQueue;import java.util.concurrent.ExecutorService;import java.util.concurrent.Executors;import java.util.concurrent.LinkedBlockingDeque;import java.util.concurrent.TimeUnit;public class Restaurant {Meal meal;Customer customer=new Customer(this);Chef chef=new Chef(this);BlockingQueue<Meal> queue=new LinkedBlockingDeque<Meal>(1);ExecutorService exec=Executors.newCachedThreadPool();public Restaurant(){exec.execute(customer);exec.execute(chef);}public static void main(String[] args) {new Restaurant();}}class Meal{private final int orderNum;public Meal(int orderNum){this.orderNum=orderNum;}public String toString(){ return "Meal "+orderNum;}}class Customer implements Runnable{private Restaurant rest;public Customer(Restaurant rest){this.rest=rest;}public void run(){try{while(!Thread.interrupted()){rest.meal=rest.queue.take();System.out.println("customer got "+rest.meal);}}catch(InterruptedException ex){System.out.println("customer interrupted");}}}class Chef implements Runnable{private Restaurant rest;private int count=0;public Chef(Restaurant rest){this.rest=rest;}public void run(){try{while(!Thread.interrupted()){if(++count==10){System.out.println("out of food!");rest.exec.shutdownNow();}rest.meal=new Meal(count);rest.queue.put(rest.meal);System.out.println("order up!");TimeUnit.MILLISECONDS.sleep(100);}}catch(InterruptedException e){System.out.println("chef interrupted");}}}






原创粉丝点击