/*
* 多线程-消费者和生产者模式
* 在实现消费者生产者模式的时候必须要具备两个前提,一是,必须访问的是一个共享资源,二是必须要有线程锁,且锁的是同一个对象
* */
1 /*资源类中定义了name(名字):用来区分消费者还是生产者 2 * 定义了flag标记:用来区分有没有货物(默认生产一个就要消费一个) 3 * 定义了count(生产的个数统计) 4 * set方法:用来生产商品 5 * out方法:用来消费商品*/ 6 class TestSource{ 7 private String name=null; 8 private boolean flag=false; 9 private int count=0; 10 /*先通过flag标记判断有没有商品,有商品则等待,没有则生产商品,唤醒所有程序,并将flag标记改变*/ 11 public synchronized void set(String name){ 12 //判断是否有产品,这里用while循环,避免在多个生产者同时生产时,会出现生产多个产品,却只消费一个 13 while(flag){ 14 try { 15 wait(); 16 } catch (InterruptedException e) { 17 e.printStackTrace(); 18 } 19 } 20 //生产产品并输出 21 this.name=name+"编号"+count++; 22 System.out.println("生产"+name+"++"); 23 //改变标记 24 flag=true; 25 //唤醒所有的线程 26 notifyAll(); 27 } 28 public synchronized void out(){ 29 while(!flag){ 30 try { 31 wait(); 32 } catch (InterruptedException e) { 33 e.printStackTrace(); 34 } 35 } 36 System.out.println("消费"+name+"---"); 37 flag=false; 38 notifyAll(); 39 } 40 } 41 class Product implements Runnable{ 42 private TestSource ts=null; 43 //初始化线程里用到的资源 44 public Product(TestSource ts){ 45 this.ts=ts; 46 } 47 //重写线程里run方法 48 public void run() { 49 while(true){ 50 ts.set("生产产品"); 51 } 52 } 53 } 54 class Customer implements Runnable{ 55 private TestSource ts=null; 56 public Customer(TestSource ts){ 57 this.ts=ts; 58 } 59 public void run() { 60 while(true){ 61 ts.out(); 62 } 63 } 64 } 65 public class test { 66 public static void main(String[] args) { 67 //初始化唯一的资源 68 TestSource ts=new TestSource(); 69 //创建生产者和消费者两个对象,并传入两者共同操作的唯一资源 70 Customer cu=new Customer(ts); 71 Product pr=new Product(ts); 72 //将对象传入线程对象 73 Thread t1=new Thread(cu); 74 Thread t2=new Thread(pr); 75 Thread t3=new Thread(cu); 76 Thread t4=new Thread(pr); 77 //开启线程 78 t1.start(); 79 t2.start(); 80 t3.start(); 81 t4.start(); 82 } 83 }
/*在java1.5版本以后,用lock和unlick代替了synchronized关键字
* 用await()代替了wait()方法
* 用signal()代替了notify()
* 这里的signal可以指定唤醒莫一类的线程,而不是像notifyAll,必须全部唤醒
这里我们对上面的代码进行一定的改写*/
1 class TestSource{ 2 private String name=null; 3 private boolean flag=false; 4 private int count=0; 5 //定义lock,用来代替synchronized关键字 6 private Lock lock=new ReentrantLock(); 7 private Condition condition_pro=lock.newCondition(); 8 private Condition condition_con=lock.newCondition(); 9 public void set(String name){ 10 //对代码段进行上锁 11 lock.lock(); 12 try { 13 while(flag){ 14 try { 15 //wait(); 16 //调用生产者控制方法 17 condition_pro.await(); 18 } catch (InterruptedException e) { 19 e.printStackTrace(); 20 } 21 } 22 this.name=name+"编号"+count++; 23 System.out.println("生产"+name+"++"); 24 flag=true; 25 //notifyAll(); 26 //唤醒消费者线程 27 condition_con.signal(); 28 } finally{ 29 //解锁,让其他进程进入访问 30 lock.unlock(); 31 } 32 33 34 } 35 public void out(){ 36 lock.lock(); 37 try{ 38 while(!flag){ 39 try { 40 //wait(); 41 condition_con.await(); 42 } catch (InterruptedException e) { 43 e.printStackTrace(); 44 } 45 } 46 System.out.println("消费"+name+"---"); 47 flag=false; 48 //notifyAll(); 49 condition_pro.signal(); 50 }finally{ 51 lock.unlock(); 52 } 53 54 } 55 }