线程锁和条件变量,生产者消费者示例

时间:2011-06-17 07:25:50

标签: java multithreading

我必须使用多线程编写这个生产消费者应用程序。我编写了以下java代码但是已经能够找出它出错的地方。另外,我想知道我的班级设计是否合适,或者我的编码风格是否合适。

提前致谢!!!

修改

我修改了产品消费者代码:但它仍有一些问题。

import java.util.*;
import java.lang.Thread;

public class pc_example {

public static void main (String [] args) {
    Store store = new Store( 10 );
    produce p = new produce(store);
    consume c = new consume (store);
    p.start();
    c.start();
}

}

class Store {
public Queue<Integer> Q;
public int max_capacity;

Store( int max_capacity ) {
    Q = new LinkedList<Integer>();
    this.max_capacity = max_capacity;
}

}

class produce extends Thread {

private Store store;
private int element;

produce ( Store store ) {
    this.store = store;
    this.element = 0;
}



public void put() {
    synchronized (store) {
        if (store.Q.size() > store.max_capacity) {
            try {
                wait();
            } catch (InterruptedException e) {}
        }
        else {
            element ++;
            System.out.println( "Producer put: " + element );
            store.Q.add(element);
            notify();
        }               
    }           
}

}

class consume extends Thread {
private int cons;
private Store store;

consume (Store store) {
    this.store = store;
    this.cons = 0;
}

public void get() {
    synchronized (store) {
        if (store.Q.size() == 0) {
            try {
                wait();
            } catch (InterruptedException e) {}
        }
        else {
            int a = store.Q.remove();
            System.out.println( "Consumer put: " + a );
            cons++;

            if (store.Q.size() < store.max_capacity)
                notify();
        }
    }
}

}

7 个答案:

答案 0 :(得分:1)

有关完整示例,请参阅BlockingQueue的java api中的producer-consumer示例。


代码中有几个错误。对于第一个,生产者和消费者没有使用相同的队列,例如有两个队列实例。其次,notifywait方法也在不同的对象上运行。

让你的例子工作需要几件事:

  1. 只有一个队列
  2. 线程安全处理队列
  3. 处理通知并等待同一个对象
  4. 生产者代码可以重写为:

    public void produce() {
        int i = 0;
        while (i < 100) {
            synchronized(Q) {
                if (Q.size() < max_capacity) {
                    Q.add(i);
                    System.out.println("Produced Item" + i);
                    i++;
                    Q.notify();
                } else {
                    try {
                        Q.wait();
                    } catch (InterruptedException e) {
                        System.out.println("Exception");
                    }
                }
            }
        }
    }
    

答案 1 :(得分:1)

您正在创建两个具有自己队列的Producer_Consumer实例,因此之间没有共享。您不应该在类中实例化队列,而是将其作为构造函数参数提供给外部。

class Producer_Consumer extends Thread {

 private final Queue<Integer> queue;

 Producer_Consumer(int mode, Queue<Integer> queue)
 {
    this.queue = queue;
 }

 public static void main(String[] args)
 {
   Queue<Integer> queue = new LinkedQueue<Integer>();
   Producer_Consumer produce = new Producer_Consumer(queue, 2);
   Producer_Consumer consume = new Producer_Consumer(queue, 1);
   produce.start();
   consume.start();   
 }
}

可以使用java.util.concurrent包中的阻止队列进行进一步改进。实际上不需要使用Object的方法wait()notify()来执行此类任务。

答案 2 :(得分:0)

1,使用合适的类型。你的模式比en枚举更好,而不是int 2,线程之间的管道Q实际上没有共享,因为它没有被声明为静态 无论如何你都会遇到问题,因为链表不同步 同步produce()consume()没有任何区别。

答案 3 :(得分:0)

这是BlockingQueue的用途。

答案 4 :(得分:0)

您的每个对象都在处理

的不同实例
Queue<Integer> Q

所以制作人把东西放在一个,但消费者永远不会看到那个 - 它试图从Q中获取永远不会放入任何东西的物品。

但是,一旦解决了这个问题,就需要确保以线程安全的方式处理Queue<>对象。虽然produce()consume()方法都是同步的,但由于您正在处理两个不同的Producer_Consumer对象,因此此级别的同步将无济于事。他们需要以其他方式同步对共享资源的访问。

答案 5 :(得分:0)

我建议查看java.util.concurrent中的类(可从Java 1.5获得)。特别是,您可以使用BlockingQueue而不是Queue。

它允许您制作:

try {
    while(true) { queue.put(produce()); }
} catch (InterruptedException ex) { ... handle ...}

并消费:

try {
   while(true) { consume(queue.take()); }
 } catch (InterruptedException ex) { ... handle ...}

Otherwize,(如果这是对java同步的练习),你应该

  • 提高字段的可见性(为什么只有max_capacity是私有的?)
  • 改进设计(我更喜欢为生产者和消费者创建两个单独的类)
  • 确保制作人和消费者等待并通知 SAME 对象
  • 让生产者和消费者在同一个队列上工作

答案 6 :(得分:0)

Thread类中缺少运行方法。所以你的线程确实开始并完成了什么。重命名put和get方法以运行和使用while循环。另请注意,您需要调用通知并在商店(监视器)上等待。

public void run() {

        while(true){
        synchronized (store) {
            if (store.Q.size() > store.max_capacity) {
                try {
                    store.wait();
                } catch (InterruptedException e) {}
            }
            else {
                element ++;
                System.out.println( "Producer put: " + element );
                store.Q.add(element);
                store.notify();
            }               
        }
    }
    }