读书人

线程同步的一个例子-类似于生产者消费

发布时间: 2012-12-25 16:18:28 作者: rapoo

线程同步的一个例子-类似于生产者消费者问题

import java.util.Stack;/* * 多线程同步例子:当厨师线程开始执行put方法或者服务员开始get方法时,都必须先获取MediContainer对象的锁, * 如果该锁被其他线程占用,另一个线程就只能在锁池中等待。这种锁机制使得厨师线程执行put方法的整个过程中 * ,服务员线程不会执行get方法,同样,在服务员线程在执行get方法的整个过程中,厨师线程不执行put方法。 *  * 注意,一个对象的wait方法和notify方法的调用应该放在同步代码块中,并且同步代码块采用这个对象的锁,   若果违背了这个规则,尽管在编译时不会检查这种错误,但在运行时会跑出IllegalMonitorException异常 */public class MutilThreadTest {public static void main(String args[]){MediContainer med=new MediContainer(5);Thread thread[]={new Cook(med),new Cook(med),new Waitress(med),new Waitress(med),new Waitress(med)};thread[0].setName("cooker1");thread[1].setName("cooker2");thread[2].setName("waitress1");thread[3].setName("waitress2");thread[4].setName("waitress3");for(int i=0;i<thread.length;i++){//同时启动两个厨师线程,3个服务员线程thread[i].start();}try {Thread.sleep(2000);//运行2s后停止运行med.setStop(true);System.out.println("over");} catch (InterruptedException e) {e.printStackTrace();}for(int i=0;i<thread.length;i++){thread[i].stop();}}}class MediContainer{//定义食物存储容器public static  Stack<Dish> slot=new Stack<Dish>();public int slotCount;public boolean stopflag=false;public MediContainer(int slotcount){this.slotCount=slotcount;}public void setStop(boolean flag){this.stopflag=flag;}public boolean isStop(){return this.stopflag;}public void put(Dish dish){//厨师放菜操作,当slot容器中炒菜数量为最大值时,该容器对象this.wait(),此时调用该方法的线程进入该对象的锁池synchronized(this){this.notifyAll();//唤醒对象等待池中其余的等待线程,即JVM将该对象等待池中的对象都移到锁池中,在这里等待获得锁//实际意义是,通知在等待池中的线程(准备从容器中取炒菜的服务员线程)准备到锁池中准备执行while(slot.size()==this.slotCount){try {System.out.println(Thread.currentThread().getName()+"厨师等待放菜....");this.wait();//此时,容器已满,厨师放弃对象锁和cpu进入该对象的等待池中} catch (InterruptedException e) {e.printStackTrace();}}slot.push(dish);System.out.println(Thread.currentThread().getName()+"完成一个炒菜,此时炒菜数量:"+slot.size());}}public  Dish get(){synchronized(this){this.notifyAll();//唤醒对象等待池中其余的等待线程,即JVM将该对象等待池中的对象都移到锁池中,在这里等待获得锁;//实际意义是,通知在等待池中的线程(准备往容器中放炒菜的厨师线程)准备到锁池中准备执行while(slot.size()==0){try{System.out.println(Thread.currentThread().getName()+"服务员等待端菜....");this.wait();}catch(InterruptedException e){e.printStackTrace();}}System.out.println(Thread.currentThread().getName()+"服务员取走一个炒菜,此时还剩炒菜数量:"+(slot.size()-1));return slot.pop();}}}class Cook extends Thread{//定义一个厨师线程private int id;MediContainer med;public static int number=1;public Cook(MediContainer med){this.id=number++;this.med=med;}public void run(){while(!med.isStop()){Dish dish=new Dish(id);med.put(dish);//该方法是同步方法,此时该对象必须获取med对象的同步锁,如果该锁被其他线程占用,则该对象进入med对象的锁池中阻塞try {Thread.sleep(10);//放弃cpu,将运行机会给别的线程} catch (InterruptedException e) {e.printStackTrace();}}}}class Waitress extends Thread{private int id;MediContainer med;public static int number=1;public Waitress(MediContainer med){this.id=number++;this.med=med;}public void run(){while(!med.isStop()){Dish dish=med.get();//该方法是同步方法,此时该对象必须获取med对象的同步锁,如果该锁被其他线程占用,则该对象进入med对象的锁池中阻塞try {Thread.sleep(200);//放弃cpu,将运行机会给别的线程} catch (InterruptedException e) {e.printStackTrace();}}}}class Dish{public int id;public Dish(int id){this.id=id;}}
?

读书人网 >编程

热点推荐