Java 线程锁和条件变量,生产者-消费者示例
我必须使用多线程编写这个productconsumer应用程序。我写了下面的java代码,但是没有;I don’我想不出哪里出了问题。我还想知道我的类设计是否合适,或者我的编码风格是否合适 提前感谢 编辑 我已经修改了产品消费者代码:但它仍然有一些问题Java 线程锁和条件变量,生产者-消费者示例,java,multithreading,Java,Multithreading,我必须使用多线程编写这个productconsumer应用程序。我写了下面的java代码,但是没有;I don’我想不出哪里出了问题。我还想知道我的类设计是否合适,或者我的编码风格是否合适 提前感谢 编辑 我已经修改了产品消费者代码:但它仍然有一些问题 import java.util.*; import java.lang.Thread; public class pc_example { public static void main (String [] args) { Sto
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();
}
}
}
类消耗扩展线程{
私营机构;
私人店铺;
消费(商店){
this.store=商店;
这是0.cons=0;
}
公开作废获取(){
已同步(存储){
if(store.Q.size()==0){
试一试{
等待();
}捕获(中断异常e){}
}
否则{
int a=store.Q.remove();
System.out.println(“用户输入:+a”);
cons++;
if(store.Q.size()
}有关完整示例,请参阅java api中的生产者-消费者示例
代码中有几个错误。首先,生产者和消费者不使用同一队列,例如,有两个队列实例。其次,
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");
}
}
}
}
}
public void product(){
int i=0;
而(i<100){
同步(Q){
if(Q.size()<最大容量){
Q.添加(i);
系统输出打印项次(“生产项目”+i);
i++;
Q.通知();
}否则{
试一试{
Q.等待();
}捕捉(中断异常e){
System.out.println(“例外”);
}
}
}
}
}
您正在创建两个生产者和消费者的实例,它们都有自己的队列,因此它们之间没有共享。您不应该在类中实例化队列,而应该在外部将其作为构造函数参数提供
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();
}
}
类生产者\消费者扩展线程{
私有最终队列;
生产者\消费者(整数模式,队列)
{
this.queue=队列;
}
公共静态void main(字符串[]args)
{
Queue Queue=new LinkedQueue();
生产者消费者产品=新生产者消费者(队列,2);
生产者消费者消费=新生产者消费者(队列,1);
product.start();
consume.start();
}
}
根据建议,可以使用java.util.concurrent
包中的阻塞队列进行进一步的改进。对于此类任务,确实不需要使用对象的方法wait()
和notify()
。1,使用适当的类型。您的模式最好使用en枚举,而不是int。
2、线程之间的管道Q实际上没有共享,因为它没有声明为静态。
由于linkedlist未同步,您可能会遇到问题。
同步product()
和consume()
没有区别。这就是a的用途。您的每个对象都在一个不同的
Queue<Integer> Q
队列Q
因此,制作人把东西放进一个盒子里,但消费者从来不看这个盒子——它试图从一个Q
盒子里得到东西,而这个盒子里从来没有放过任何东西
但是,一旦解决了这个问题,就需要确保以线程安全的方式处理队列
对象。虽然product()
和consume()
方法都是同步的,但此级别的同步不会有帮助,因为您处理的是两个不同的生产者和消费者
对象。他们需要以其他方式同步对共享资源的访问。我建议查看java.util.concurrent(可从java 1.5获得)中的类。特别是,您可以使用BlockingQueue而不是队列
它允许您制作:
try {
while(true) { queue.put(produce()); }
} catch (InterruptedException ex) { ... handle ...}
和消费:
try {
while(true) { consume(queue.take()); }
} catch (InterruptedException ex) { ... handle ...}
Otherwize(如果这是一个关于java同步的练习),您应该
- 提高字段的可见性(为什么只有最大容量是专用的?)
- 改进设计(我更喜欢为生产者和消费者创建两个单独的类)
- 确保生产者和消费者等待并通知同一对象
- 使生产者和消费者在同一队列上工作
线程类中缺少Run方法。所以你的线程开始和结束时什么都不做。重命名要在while循环中运行和使用的put和get方法。还要注意的是,您需要调用notify并在商店(监视器)上等待
哼,因为队列是在线程之间共享的,所以在访问之前必须锁定它@巴甫洛维奇:你能解释一下阻塞队列和java.util.concurrent包吗?@dacwe我同意,但如果你想教别人,最好一步一步地教step@AmmSokun在这里:花一些时间阅读Javadoch。一个类的两个实例试图使用共享资源执行相反的任务,这需要使用同步。我说这两个实例实际上是两个正在运行的线程,对吗。在一个实例中,product方法正在运行,而在另一个实例中,consume方法正在运行。我也同意我应该有一个全局队列。还有,如何在java中声明全局变量呢?好的,我同意存在两个不同的Q对象。但是,一旦我同步了方法本身,我就不理解同步Q对象的必要性?如果调用
object2.notify()
它将通知一个线程等待该对象(object2
)。在您(当前)的示例中
Queue<Integer> Q
try {
while(true) { queue.put(produce()); }
} catch (InterruptedException ex) { ... handle ...}
try {
while(true) { consume(queue.take()); }
} catch (InterruptedException ex) { ... handle ...}
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();
}
}
}
}