java线程之多个生产者消费者

温故一下上一节所学习的生产者消费者代码:

两个线程时:

通过标志位flag的if判断和同步函数互斥较好解决两个线程,一个生产者、一个消费者交替执行的功能

类名:ProducterConsumerDemo.java

代码:

 1 class  ProducterConsumerDemo
 2 {
 3     public static void main(String[] args) 
 4     {
 5         Resources  r =new Resources();
 6         Productor  pro =new Productor(r);
 7         Consumer   con = new Consumer(r);
 8         
 9         Thread t1 =new Thread(pro);
10         Thread t2 =new Thread(con);
11         t1.start();
12         t2.start();
13         System.out.println("Hello World!");
14     }
15 }
16 
17 class Resources
18 {
19     private String name;
20     private int count =1;
21     private boolean flag =false;
22 
23     public synchronized void set(String name)
24     {
25        if(flag)
26            try{this.wait();}catch(Exception e){}
27        this.name = name+"--"+count++;
28 
29        System.out.println(Thread.currentThread().getName()+"生产者"+this.name);
30        flag =true;
31        //唤醒对方进程
32        this.notify();
33 
34     }
35     public synchronized void out()
36     {
37        if(!flag)
38            try{this.wait();}catch(Exception e){}
39        
40        System.out.println(Thread.currentThread().getName()+" ....消费者...."+this.name);
41        flag =false;
42        //唤醒对方进程
43        this.notify();
44 
45     }
46 }
47 
48 class Productor implements Runnable
49 {
50     private Resources res;
51     Productor(Resources res){
52         this.res =res;
53     }
54     public void run(){
55         while(true){
56             res.set("++商品++");
57         }
58     }
59 
60 }
61 
62 class Consumer  implements Runnable
63 {
64     private Resources res;
65     Consumer(Resources res){
66         this.res =res;
67     }
68     public void run(){
69         while(true){
70             res.out();
71         }
72     }
73 
74 }
ProducterConsumerDemo.java

 

如果再多加上两个线程呢?

  即把其中的ProducterConsumerDemo类改为如下:

class  ProducterConsumerDemo2
{
    public static void main(String[] args) 
    {
        Resources  r =new Resources();
        Productor  pro =new Productor(r);
        Consumer   con = new Consumer(r);
        
        Thread t1 =new Thread(pro);
        Thread t2 =new Thread(pro);//多个生产者
        Thread t3 =new Thread(con);
        Thread t4 =new Thread(con);//多个消费者
        t1.start();
        t2.start();
        t3.start();
        t4.start();
        System.out.println("Hello World!");
    }
}

运行后发现,加上t3和t4之后结果就错了。

  为什么两个线程的时候执行结果正确而四个线程的时候就不对了呢?

  因为线程在wait()的时候,接收到其他线程的通知,即往下执行,不再进行判断。两个线程的情况下,唤醒的肯定是另一个线程;但是在多个线程的情况下,执行结果就会混乱无序。

  比如,一个可能的情况是,一个增加线程执行的时候,其他三个线程都在wait,这时候第一个线程调用了notify()方法,其他线程都将被唤醒,然后执行各自的增加或减少方法。

  解决的方法就是:在被唤醒之后仍然进行条件判断,去检查要改的数字是否满足条件,如果不满足条件就继续睡眠。

                           1)把两个方法中的if改为while即可。

           2)需要将notify()改成notifyAll()

代码:

 1 /*
 2 ProducterConsumerDemo解决了只有两个线程共享资源的生产消费问题,主要利用标志位的互斥解决
 3 
 4 本程序致力于解决多出现多个生产者,多个消费者的时候,依然能够达到生产一次,消费一次的功能
 5  6 解决的方法就是:1)在被唤醒之后仍然进行条件判断,去检查要改的数字是否满足条件,如果不满足条件就继续睡眠。把两个方法中的if改为while即可。
 7 当然,此时仍会出现问题,就是所以线程都等待,失去资格
 8                 2)需要将notify()改成notifyAll()
 9 */
10 
11 class  ProducterConsumerDemo2
12 {
13     public static void main(String[] args) 
14     {
15         Resources  r =new Resources();
16         Productor  pro =new Productor(r);
17         Consumer   con = new Consumer(r);
18         
19         Thread t1 =new Thread(pro);
20         Thread t2 =new Thread(pro);//多个生产者
21         Thread t3 =new Thread(con);
22         Thread t4 =new Thread(con);//多个消费者
23         t1.start();
24         t2.start();
25         t3.start();
26         t4.start();
27         System.out.println("Hello World!");
28     }
29 }
30 
31 class Resources
32 {
33     private String name;
34     private int count =1;
35     private boolean flag =false;
36 
37     public synchronized void set(String name)
38     {  //1)循环判断
39        while(flag)
40            try{this.wait();}catch(Exception e){}
41        this.name = name+"--"+count++;
42 
43        System.out.println(Thread.currentThread().getName()+"生产者"+this.name);
44        flag =true;
45        //2)唤醒所有进程
46        this.notifyAll();
47 
48     }
49     public synchronized void out()
50     {
51        //1)循环判断
52        while(!flag)
53            try{this.wait();}catch(Exception e){}
54        
55        System.out.println(Thread.currentThread().getName()+" ....消费者...."+this.name);
56        flag =false;
57        //2)唤醒所有进程
58        this.notifyAll();
59 
60     }
61 }
62 
63 class Productor implements Runnable
64 {
65     private Resources res;
66     Productor(Resources res){
67         this.res =res;
68     }
69     public void run(){
70         while(true){
71             res.set("++商品++");
72         }
73     }
74 
75 }
76 
77 class Consumer  implements Runnable
78 {
79     private Resources res;
80     Consumer(Resources res){
81         this.res =res;
82     }
83     public void run(){
84         while(true){
85             res.out();
86         }
87     }
88 
89 }

效果:

转载于:https://www.cnblogs.com/shuqingstudy/p/5057382.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值