首页 > 解决方案 > java中的线程生产者消费者

问题描述

以下是消费者生产者问题代码,但代码未按预期工作。在这里,消费者和生产者应该只是生产和消费一个对象。

public class ProducerConsumer {
    private static LinkedList<Integer> linkedList = new LinkedList<>();

    public static void main(String a[]) throws InterruptedException {
        Thread producer = new Thread(new Runnable() {

            @Override
            public void run() {
                synchronized(this) {
                    while (linkedList.size() == 1) {
                        try {
                            wait();
                        } catch(InterruptedException e) {
                            e.printStackTrace();
                        }
                    }
                    System.out.println("Produced");
                    linkedList.add(1);
                    notify();
                    try {
                        Thread.sleep(1000);
                    } catch(InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            }
        });

        Thread consume = new Thread(new Runnable() {
            @Override
            public void run() {
                // produce
                synchronized(this) {
                    while (linkedList.isEmpty()) {
                        try {
                            wait();
                        } catch(InterruptedException e) {
                            e.printStackTrace();
                        }
                    }
                    System.out.println("Consumed");
                    linkedList.removeFirst();
                    notify();
                    try {
                        Thread.sleep(1000);
                    } catch(InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            }
        });
        producer.start();
        consume.start();
        producer.join();
        consume.join();

    }
}

我们得到的输出为: Produced

程序挂起。

请帮助提供可能的解决方案/解释

标签: javamultithreadingproducer-consumer

解决方案


使用共享锁。在发布的代码中,每个 Runnable 都将自己用作锁,因此不会发生实际的锁定。

当一个线程等待时,另一个线程需要在同一个锁上调用 notify 以唤醒等待的线程。我们从您的日志中得知 Producer 线程执行其操作,但由于通知作用于与 Consumer 正在使用的锁不同的锁,因此 Consumer 线程永远不会唤醒。

更改代码以使用共享锁有效:

import java.util.*;

public class ProducerConsumer { private static LinkedList linkedList = new LinkedList();

public static void main(String a[]) throws InterruptedException {
    final Object lock = new Object();
    Thread producer = new Thread(new Runnable() {
        @Override
        public void run() {
            synchronized (lock) {
                while (linkedList.size() ==1) {
                    try {
                        lock.wait();
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
                System.out.println("Produced");
                linkedList.add(1);
                lock.notify();
                try {
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }
    });

    Thread consume = new Thread(new Runnable() {
        @Override
        public void run() {
            // produce
            synchronized (lock) {
                while (linkedList.isEmpty()) {
                    try {
                        lock.wait();
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
                System.out.println("Consumed");
                linkedList.removeFirst();
                lock.notify();
                try {
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }
    });
    producer.start();
    consume.start();
    producer.join();
    consume.join();

}

}

输出是:

c:\example>java ProducerConsumer
Produced
Consumed

我认为这是你所期待的。

顺便说一句,看看为队列的简单实现写的另一个答案;你最好保护共享数据结构而不是将代码放在访问数据结构的线程中,特别是看看代码编写有多容易。


推荐阅读