制片人消费者对线程的误解

时间:2016-11-20 09:57:10

标签: java multithreading producer-consumer

我希望ProducerThread产生最多10个随机值,然后期望ConsumerThread消费者使用Queue的值。某处生产者正在生成多次添加值。我有一个概念,当我们在一个对象上调用notify而不是Thread会释放锁并给予期望更新的Thread机会。

以下是代码,请更正我的理解。

public class ProducerThread extends Thread {

    Queue<Integer> values;

    ProducerThread(Queue<Integer> values) {
        this.values = values;
    }

    public void run() {
        while(true) {
            synchronized(values) {
                double totalValues = Math.random()*10;
                System.out.println("Going to populate total values:" + totalValues);

                for (int i = 1; i <= totalValues; i++) {
                    values.add(i);
                    System.out.println("Value updated: " + i);
                    try {
                        Thread.sleep(1000);
                    } catch (InterruptedException e) {
                        // TODO Auto-generated catch block
                        e.printStackTrace();
                    }
                }
                values.notify();
            }
        }
    }

}



public class ConsumerThread extends Thread {
    Queue<Integer> values;

    ConsumerThread(Queue<Integer> values) {
        this.values = values;
    }

    @Override
    public void run() {
        while(true) {
            synchronized (values) {

                try {
                    // Consumer Thread waits until values are populated by Producer Thread
                    if(values.isEmpty()) {
                        values.wait();
                    }

                    Iterator<Integer> iterateValues = values.iterator();
                    System.out.println("Going to consume values: " + values.size());
                    while (iterateValues.hasNext()) {
                        Integer removedValue = iterateValues.next();
                        System.out.println("Value deleted: " + removedValue);
                    }
                    values.clear();
                } catch (InterruptedException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                }
            }
        }
    }
}


public class Test {
    public static void main(String[] args) {
        Queue<Integer> values = new LinkedList<Integer>();
        ProducerThread producer = new ProducerThread(values);
        ConsumerThread consumer = new ConsumerThread(values);

        consumer.start();
        producer.start();

    }
}

1 个答案:

答案 0 :(得分:1)

啊哈!你遇到了可怕的竞争条件!

在您notifyProducerThread返回后,所述线程仍然锁定。被ConsumerThread唤醒的notify会看到锁定无法使用,并会等到它可用。

然后ProducerThread放弃锁定,然后它将进入与ConsumerThread的竞赛,以便通过重新输入{{1}来取回锁定ProducerThread阻止,synchronized通过必须从ConsumerThread返回。无法保证其中哪些会赢。

如果您希望wait在生成更多内容之前等待消耗的项目,则应考虑针对该方案进行另一次等待/通知。

编辑:这张图片可能有助于更清楚地解释事情。 Wait Notify Diagram