我有两根线。第一个是生产者(class Deliver
),第二个是消费者(class Produce
)。我想模拟门制作者。所以生产者交付木材,消费者就能生产出一扇门。但我并不真正了解如何在这两个线程之间进行交流。现在,当我运行我的程序,只有木材是交付,但门没有生产。我不明白为什么。
public class Deliver implements Runnable {
private static int MAX_STOCKPILE = 15;
private Integer wood;
public Deliver(Integer wood) {
this.wood = wood;
new Thread(this, "Deliver").start();
}
public synchronized void deliver() throws InterruptedException{
Thread.sleep(500);
if (wood < MAX_STOCKPILE) {
wood++;
System.out.println("Wood delivered" + " | Wood stockpile: " + wood);
notify();
}
else {
wait();
}
}
@Override
public void run() {
while (true) {
try {
deliver();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
public class Produce implements Runnable{
private Integer wood;
public Produce(Integer wood) {
this.wood = wood;
new Thread(this, "Produce").start();
}
public synchronized void produce() throws InterruptedException{
Thread.sleep(1000);
if (wood == 10) {
wood -= 10; //produce
System.out.println("Doors produced");
notify();
}
else {
wait();
}
}
@Override
public void run() {
while (true) {
try {
produce();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
public class Main {
public static void main(String[] args) {
Integer wood = 0;
new Deliver(wood);
new Produce(wood);
}
}
发布于 2017-01-31 18:20:41
现在,当我运行我的程序,只有木材是交付,但门没有生产。我不明白为什么
您的代码存在多个问题:
synchronized
时,任何进入该方法的线程都将获得this
上的锁(即调用该方法的实例)。由于this
in Deliver
引用Deliver
实例,而this
在Produce
中引用Produce
实例,因此wait
和notify
调用在这种情况下实际上是无用的,因为它们对相同的对象不感兴趣。Deliver
和Produce
都将修改从main
传递给他们的同一个Integer
,但事实并非如此。尽管如此,我强烈建议您考虑使用像ArrayBlockingQueue
这样的工具来解决这个问题,而不是用wait
和notify
重新发明轮子。
发布于 2017-01-31 16:59:37
变化
if (wood == 10) {
至
if (wood >= 10) {
以防线程在== 10时没有捕获它
发布于 2017-01-31 17:10:27
值得注意的是,Integer是不可变的。
当您更改对Integer的引用时,您将创建一个与前一个对象无关的新对象。
您想要的是一个在两个线程之间共享的对象,所以当您更改值(而不是引用)时,它们看到的是相同的值。
例如:
wood -= 10;
是相同的
wood = Integer.valueOf(wood.intValue() - 10);
我建议使用AtomicInteger
并对其进行final
引用,以确保您不会意外地尝试更改引用。
正如Andrew所建议的那样,如果锁定、通知/等待无关对象,则没有任何线程安全。一旦有了共享对象,就必须锁定、通知/等待该共享对象。
https://stackoverflow.com/questions/41963057
复制相似问题