我必须使用多线程编写这个生产消费者应用程序。我编写了以下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();
}
}
}
}
答案 0 :(得分:1)
有关完整示例,请参阅BlockingQueue的java api中的producer-consumer示例。
代码中有几个错误。对于第一个,生产者和消费者没有使用相同的队列,例如有两个队列实例。其次,notify
和wait
方法也在不同的对象上运行。
让你的例子工作需要几件事:
生产者代码可以重写为:
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同步的练习),你应该
答案 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();
}
}
}
}