Java 线程生产者消费者算法无法正常工作

Posted

技术标签:

【中文标题】Java 线程生产者消费者算法无法正常工作【英文标题】:Java Threads Producer Consumer Algorithm not working properly 【发布时间】:2011-09-04 20:32:48 【问题描述】:

我正在尝试学习线程,因此我编写了一个示例生产者消费者问题,其中生产者产生从 1 到 10 的数字,消费者必须显示它们。但只有消费者显示数字 1 并停止。

正如我所说,程序写得不好,可能很荒谬,但我仍然想弄清楚为什么从 1 到 10 的所有数字都没有打印出来,因为当我编写代码而不是从示例中时,我会记得最好。

我正在使用两个变量来跟踪生产者或消费者活动的完成情况,以便我可以执行另一个。

/getStatus(消费者 C) 传递消费者引用,以便生产者获得消费者的引用..它可以用来了解消费者的状态..就是这样../

import java.lang.Math;
public class Hello

public static void main(String args[]) 

    System.out.println("---1");
    new Consumer().start();





class Producer extends Thread

public int produce = 0;
public Consumer consumerObj =null;
int count = 1;
boolean producerStatus = false;

public void run()

    System.out.println("---4");
    synchronized(this)

        do

            System.out.println("---6");
            produce = produce+1;
            producerStatus = true;
            notify();
            consumerObj.consumerStatus = false;
            System.out.println("---9");
            count = count+1;

        while(count<=10 && consumerObj.getStatus());

    



public int getItem()
    return produce;




public boolean getStatus(Consumer c)
    consumerObj = c;
    return producerStatus;





class Consumer extends Thread

boolean consumerStatus = false;
int count =0;
public void run()

    System.out.println("---2");
    Producer p = new Producer();
    p.getStatus(this);
    p.start();
    try
        System.out.println("---3");
        synchronized(p)
            System.out.println("---5");
            p.wait();

            System.out.println("---8");
        
    
    catch(Exception e)
            System.out.println("exception");
    

    synchronized(p)
        try
            while(p.getStatus(this) && count<=9 )

                System.out.println("---7");
                int consume = p.getItem();
                System.out.println("the produced item is ----->"+consume);
                count = count+1;
                p.producerStatus  = false;
                consumerStatus = true;
                p.wait();                   
                System.out.println("---10");

            
        
        catch(Exception e)
            System.out.println("exception");
        

    



public boolean getStatus()

    return consumerStatus;



输出:

---1
---2
---3
---5
---4
---6
---9
---8
---7
the produced item is ----->1
---10

在 .. Suraj 的输入之后 .. 现在程序运行良好 .. 见下文 ..

导入 java.lang.Math; 公共课你好

public static void main(String args[]) 

    System.out.println("---1");
    new Consumer().start();





class Producer extends Thread

public int produce = 0;
public Consumer consumerObj =null;
int count = 1;
boolean producerStatus = false;

public void run()

    System.out.println("---4");

        do
            if(consumerObj.getStatus())


            System.out.println("---6");
            produce = produce+1;
            System.out.println("---9 -- >produce is -->"+produce);
            producerStatus = true;
            synchronized(this)

            notify();
            System.out.println("---6.111");
            

            consumerObj.consumerStatus = false;
            count = count+1;


            


        while(count<=10);




public int getItem()

    return produce;



public boolean getStatus(Consumer c)

    consumerObj = c;
    return producerStatus;







class Consumer extends Thread

boolean consumerStatus = true;
int count =1;
public void run()

    System.out.println("---2");
    Producer p = new Producer();
    p.getStatus(this);
    p.start();//can a thread1 wait on an thread2 before the thread2 hass tarted and in this case wll notify on the scnd thread reaally notify therad1 ..
    try
        System.out.println("---3");
        synchronized(p)
            System.out.println("---5");
            p.wait();

            System.out.println("---8");
        
    
    catch(Exception e)
            System.out.println("exception");
    


        try
            while(count<=10 )

                System.out.println("---7");
                int consume = p.getItem();
                System.out.println("the produced item is ----->"+consume);
                count = count+1;
                p.producerStatus  = false;
                consumerStatus = true;
                synchronized(p)
                p.wait();   
                System.out.println("---10");        
                


            
        
        catch(Exception e)
            System.out.println("exception");
        




public boolean getStatus()

    return consumerStatus;




【问题讨论】:

【参考方案1】:

好的。 程序错误。

    消费者线程到来并等待锁定。 producer 循环中的第一次迭代将调用 notify,但不会释放锁,因为 while 循环位于同步块内。它会迭代 10 次而不释放锁,最终连续调用 10 次 notify。 但是消费者只能唤醒一次,消费者第二次调用 wait() 时它会一直等待,因为现在没有人调用 notify(因为生产者的所有 10 次迭代都结束了)

所以问题是消费者线程正在等待,但没有人通知它,因为生产者在 1 个镜头中完成了所有 10 次迭代。

【讨论】:

你的解释是结构化的,但我很少有 dbts .. 你的意思是在每次通知之后,生产者都放弃了锁,为什么要这样 ..?所以为了使代码正常工作,我将 while 循环带出同步块。 我的另一个疑问是我的生产者执行取决于消费者的状态..因为我在消费者中设置了一个标志,基于它我执行..然后没有我的消费者交替执行生产者怎么能连续执行..【参考方案2】:

在Producer中,你设置

consumerObj.consumerStatus = false;

并立即在循环条件中检查此值。循环在 1 个循环后结束。 之后

count = count+1;

你应该等待(等待“消费”)。

try
    this.wait();
 catch (Exception e) 
    e.printStackTrace();

消费者也有同样的问题。循环中的最后一件事应该是

p.wait();

【讨论】:

我不认为当你只有一个线程在等待时会产生差异 .. stll 试过了 .. 是的,对不起。快速浏览后写了答案。给我几分钟。 当您在生产者中说 this.wait() 时,您正在等待同一个线程,这怎么会发生? this 指生产者并在同一个类中调用 this.wait() ? 因为在我将生产者的 consumerStatus 设置为 false 之后,消费者在它执行后将其更改为 true,以便现在生产者可以执行...这是为了确保不会发生重复的生产者执行...... stll它不工作..【参考方案3】:

您应该使用 BlockingQueues。 见http://www.javamex.com/tutorials/synchronization_producer_consumer_2.shtml

上述实现效率低下,它迫使所有消费者阻止。 使用多个队列,您可以防止所有消费者阻塞。 你可以在谷歌上找到例子。 Java.util.concurrent 使用它,它的存在是有原因的。

【讨论】:

以上是关于Java 线程生产者消费者算法无法正常工作的主要内容,如果未能解决你的问题,请参考以下文章

进程,互斥锁,生产者消费者,线程

java 多线程并发系列之 生产者消费者模式的两种实现

消费者/生产者锁定 GUI 线程

Qt 中的最佳生产者/消费者线程模式

线程生成器java中的消费者

IPC 新手,无法让我的管道正常工作