首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >为什么我的消费者不使用Integer值?(生产者-消费者须等候及通知)

为什么我的消费者不使用Integer值?(生产者-消费者须等候及通知)
EN

Stack Overflow用户
提问于 2017-01-31 16:51:36
回答 4查看 174关注 0票数 0

我有两根线。第一个是生产者(class Deliver),第二个是消费者(class Produce)。我想模拟门制作者。所以生产者交付木材,消费者就能生产出一扇门。但我并不真正了解如何在这两个线程之间进行交流。现在,当我运行我的程序,只有木材是交付,但门没有生产。我不明白为什么。

代码语言:javascript
运行
复制
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);
    }
}
EN

回答 4

Stack Overflow用户

回答已采纳

发布于 2017-01-31 18:20:41

现在,当我运行我的程序,只有木材是交付,但门没有生产。我不明白为什么

您的代码存在多个问题:

  1. 当将实例方法标记为synchronized时,任何进入该方法的线程都将获得this上的锁(即调用该方法的实例)。由于this in Deliver引用Deliver实例,而thisProduce中引用Produce实例,因此waitnotify调用在这种情况下实际上是无用的,因为它们对相同的对象不感兴趣。
  2. 在Java中要记住的金科玉律是,它使用逐值语义。因此,原语和引用总是通过值传递的。虽然您可能假设DeliverProduce都将修改从main传递给他们的同一个Integer,但事实并非如此。

尽管如此,我强烈建议您考虑使用像ArrayBlockingQueue这样的工具来解决这个问题,而不是用waitnotify重新发明轮子。

票数 1
EN

Stack Overflow用户

发布于 2017-01-31 16:59:37

变化

代码语言:javascript
运行
复制
if (wood == 10) { 

代码语言:javascript
运行
复制
if (wood >= 10) { 

以防线程在== 10时没有捕获它

票数 0
EN

Stack Overflow用户

发布于 2017-01-31 17:10:27

值得注意的是,Integer是不可变的。

当您更改对Integer的引用时,您将创建一个与前一个对象无关的新对象。

您想要的是一个在两个线程之间共享的对象,所以当您更改值(而不是引用)时,它们看到的是相同的值。

例如:

代码语言:javascript
运行
复制
wood -= 10;

是相同的

代码语言:javascript
运行
复制
wood = Integer.valueOf(wood.intValue() - 10);

我建议使用AtomicInteger并对其进行final引用,以确保您不会意外地尝试更改引用。

正如Andrew所建议的那样,如果锁定、通知/等待无关对象,则没有任何线程安全。一旦有了共享对象,就必须锁定、通知/等待该共享对象。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/41963057

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档