我在生产者 - 消费者面临问题。 我的要求是:
生产者一起生产100个对象并等待消费者消费。 然后消费者消耗这100个对象并等待生产者生产。 这个过程重复进行。
条件是,生产者不应该生成,直到对象大小为0, 在对象大小为100之前,消费者不应该消费。 即。 仅批量生产和消费。
class Producer extends Thread {
private Queue<Integer> queue;
private int maxSize;
public Producer(Queue<Integer> queue, int maxSize, String name) {
super(name);
this.queue = queue;
this.maxSize = maxSize;
}
@Override
public void run() {
while (true) {
synchronized (queue) {
while (queue.size() == maxSize) {
try {
System.out.println("Queue is full, "
+ "Producer thread waiting for "
+ "consumer to take something from queue");
queue.wait();
} catch (Exception ex) {
ex.printStackTrace();
}
}
Random random = new Random();
int i = random.nextInt();
System.out.println("Producing value : " + i);
queue.add(i);
queue.notifyAll();
}
}
}
}
class Consumer extends Thread {
private Queue<Integer> queue;
private int maxSize;
public Consumer(Queue<Integer> queue, int maxSize, String name) {
super(name);
this.queue = queue;
this.maxSize = maxSize;
}
@Override
public void run() {
while (true) {
synchronized (queue) {
while (queue.isEmpty()) {
System.out.println("Queue is empty,"
+ "Consumer thread is waiting"
+ " for producer thread to put something in queue");
try {
queue.wait();
} catch (Exception ex) {
ex.printStackTrace();
}
}
System.out.println("Consuming value : " + queue.remove());
queue.notifyAll();
}
}
}
}
public class ProdConsReference {
public static void main(String args[]) {
Queue<Integer> buffer = new LinkedList<Integer>();
int maxSize = 10;
Thread producer = new Producer(buffer, maxSize, "PRODUCER");
Thread consumer = new Consumer(buffer, maxSize, "CONSUMER");
producer.start();
consumer.start();
}
}
输出:
Queue is empty,Consumer thread is waiting for producer thread to put something in queue
Producing value : 52648529
Consuming value : 52648529
Queue is empty,Consumer thread is waiting for producer thread to put something in queue
Producing value : -2128028718
Consuming value : -2128028718
任何人都可以指出我错过了什么。 提前致谢
答案 0 :(得分:1)
我正在做一个练习,所以这是我的2美分:
每次添加/删除后,您都会通知其他线程。你不应该这样做。
您想要做的是:
制片:
消费者:
您可能想要使用Conditions。
然后你应该看看zapl的方法,他在评论中说: 使用代表100个项目批次的列表队列。
共享:有工作队列(线程安全数据结构,我建议使用阻塞)。
制片人:
消费(或多个):
请注意,如果您必须保留订单,则可以只使用一个消费者,或者额外努力强制对结果进行排序。
答案 1 :(得分:0)
Thnx对您的宝贵意见和建议。 我无法理解为什么不鼓励使用LinkedList。 在我的实时项目中,我的 productionCount 将超过数百万,而且我必须分批处理10000个。 以下链接也很有帮助。 How to know if other threads have finished?
这是我的实现仅使用2个线程。一个制片人&amp;其他主要线程本身作为消费者
package threading;
import java.util.LinkedList;
import java.util.Queue;
import java.util.Set;
import java.util.concurrent.CopyOnWriteArraySet;
public class ProdConsumerApp implements ThreadCompleteListener{
boolean isProductionOver;
public static void main(String args[]) {
ProdConsumerApp prodConsumerApp = new ProdConsumerApp();
prodConsumerApp.procudeAndConsume();
}
private void procudeAndConsume(){
Queue<Integer> buffer = new LinkedList<Integer>();
int maxSize = 100;
int productionCount = 1000;
Producer producer = new Producer(buffer, maxSize, "PRODUCER", productionCount);
producer.addListener(this);
producer.start();
consume(buffer);
System.out.println("Bye");
}
public void consume(Queue<Integer> queue){
while(!isProductionOver){//check whether production completed?
synchronized (queue) {
//when queue size is 0, notify and wait.
while(queue.isEmpty()){
try {
queue.notify();
queue.wait();
} catch (Exception ex) {
ex.printStackTrace();
}
}
//consume until queue is empty.
while(!queue.isEmpty()){
System.out.println("Consuming value : " + queue.remove());
}
}
}
}
@Override
public void notifyOfThreadComplete(Thread thread) {
System.out.println("notified");
isProductionOver = true;
}
}
class Producer extends Thread {
private Queue<Integer> queue;
private int maxSize;
private int productionCount;
public Producer(Queue<Integer> queue, int maxSize, String name, int productionCount) {
super(name);
this.queue = queue;
this.maxSize = maxSize;
this.productionCount = productionCount;
}
private final Set<ThreadCompleteListener> listeners = new CopyOnWriteArraySet<ThreadCompleteListener>();
public final void addListener(final ThreadCompleteListener listener) {
listeners.add(listener);
}
public final void removeListener(final ThreadCompleteListener listener) {
listeners.remove(listener);
}
private final void notifyListeners() {
for (ThreadCompleteListener listener : listeners) {
listener.notifyOfThreadComplete(this);
}
}
@Override
public void run() {
synchronized (queue) {
for(int i=1;i<=productionCount;i++){
System.out.println("Producing value : " + i);
queue.add(i);
//when queue size is maxSize, notify and wait.
while(queue.size() == maxSize){
try {
queue.notify();
if(i==productionCount){
//if last item is produced, notify listeners that production is completed.
notifyListeners();
//exit from while() and later for() and thereby terminating Producer.
break;
}
queue.wait();
} catch (Exception ex) {
ex.printStackTrace();
}
}
}
}
}
}
interface ThreadCompleteListener {
void notifyOfThreadComplete(final Thread thread);
}