Java线程|制片人消费者:代码出了什么问题?

时间:2017-08-18 19:40:32

标签: java multithreading producer-consumer thread-synchronization

尝试学习线程的多线程和进程间通信。实施了典型的producer-consumer问题。但是,输出结果非常顺序,理想情况下使用线程时不应该这样。

好的,这是完整的代码:

public class ProducerConsumerSimulation {


public static ProducerConsumerSimulation simulation = new ProducerConsumerSimulation();


private Queue<Integer> sharedQueue = new LinkedList<Integer>();

private int MAX_LIMIT =  10;

public void produce(int i){
    synchronized (sharedQueue) {
        while(true){


            while(sharedQueue.size()==MAX_LIMIT){
                try {
                    sharedQueue.wait();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            } 
            sharedQueue.add(i);
            System.out.println("Produced: "+i);
            sharedQueue.notifyAll();
            return;


        }
    }
}

public void consume() {
    synchronized (sharedQueue) {
        while (true) {


            while (sharedQueue.isEmpty()) {
                try {
                    sharedQueue.wait();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            } 
            int i = sharedQueue.remove();
            System.out.println("Consumed: " + i);
            sharedQueue.notifyAll();
            return;


        }
    }
}

/**
 * @param args
 */
public static void main(String[] args) {


    for(int i=1;i<=5;i++){

        Runnable p = new Producer();
        Thread prod = new Thread(p);
        prod.start();
    }
    for(int i=1;i<=5;i++){

        Runnable c = new Consumer();
        Thread con = new Thread(c);
        con.start();
    }


}

}

制片人主题:

public class Producer implements Runnable {

/* (non-Javadoc)
 * @see java.lang.Runnable#run()
 */
@Override
public void run() {

    for(int i=1;i<=10;i++){
        ProducerConsumerSimulation.simulation.produce(i);
    }

}

}

消费者主题:

public class Consumer implements Runnable {

/* (non-Javadoc)
 * @see java.lang.Runnable#run()
 */
@Override
public void run() {

    for(int i=1;i<=10;i++){
        ProducerConsumerSimulation.simulation.consume();
    }

}

}

现在,当我运行程序时,生产者线程总是首先运行而不是消费者。即使我创建了多个生产者/消费者,结果也是一样的。以下是单个生产者和单个消费者的输出:

Produced: 1
Produced: 2
Produced: 3
Produced: 4
Produced: 5
Produced: 6
Produced: 7
Produced: 8
Produced: 9
Produced: 10
Consumed: 1
Consumed: 2
Consumed: 3
Consumed: 4
Consumed: 5
Consumed: 6
Consumed: 7
Consumed: 8
Consumed: 9
Consumed: 10

有人可以解释这里的行为吗?我在这里已经经历了很多答案,但是想要了解我是否有错误的实施或者其他。

1 个答案:

答案 0 :(得分:2)

首先,您应该删除自第一次迭代后返回以来实际只执行一次的两个using Syncfusion.SfImageEditor.XForms; using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; using Xamarin.Forms; using Xamarin.Forms.Xaml; namespace MashamApp { [XamlCompilation(XamlCompilationOptions.Compile)] public partial class MImageEditor : ContentPage { public MImageEditor() { InitializeComponent(); Browser.Source = "http://www.walla.co.il"; } private void backClicked(object sender, EventArgs e) { // Check to see if there is anywhere to go back to if (Browser.CanGoBack) { Browser.GoBack (); } else { // If not, leave the view Navigation.PopAsync (); } } private void forwardClicked(object sender, EventArgs e) { if (Browser.CanGoForward) { Browser.GoForward (); } } } } 循环。这会让你的代码很混乱。

现在,关于你的问题:制片人和消费者都不做两件作品/消费之间的任何事情。他们立即重新进入同步块以放入/从队列中获取内容。一个更现实的例子在将它们放入队列之前需要花费一些时间来生成值,并且需要一些时间来处理从队列中获得的值。如果在每次调用generate()或consume()之后引入任意延迟,您将开始看到更多的交错产生和消耗。

最后,请注意您通过使用LinkedList,同步块和wait / notifyAll调用来重新发明轮子。你应该只使用一个BlockingQueue,这将是你的全部。