首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >如何使用BlockingQueue解决容量为1的产品消费者问题?

如何使用BlockingQueue解决容量为1的产品消费者问题?
EN

Stack Overflow用户
提问于 2021-05-08 01:04:53
回答 1查看 40关注 0票数 1

我必须使用BlockingQueue解决生产-消费者问题。我希望它是1个元素队列。因此解决方案必须是:

生产%1消耗%1生产%2消耗%2生产%3消耗%3

但它确实是:

生产1生产2消费1消费2生产3生产4等等。

我目前使用的SynchronizedQueue是这样的:

代码语言:javascript
复制
class Producent extends Thread {
private final BlockingQueue<Integer> blockingQueue;

public Producent(BlockingQueue<Integer> blockingQueue) {
    this.blockingQueue = blockingQueue;
}

@Override
public void run() {
    for (int i = 0; i < 100; ++i) {
        try {
            System.out.println("PRODUCE: " + i);
            blockingQueue.put(i);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}
}

class Konsument extends Thread {
private final BlockingQueue<Integer> blockingQueue;

public Konsument(BlockingQueue<Integer> blockingQueue) {
    this.blockingQueue = blockingQueue;
}

public void run() {
    for (int i = 0; i < 100; ++i) {
        try {
            consume(blockingQueue.take());
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}

    private void consume(int number) {
        System.out.println("CONSUME: " + number);
    }
}

public class PKmon {
    public static void main(String[] args) {
        BlockingQueue<Integer> blockingQueue = new SynchronousQueue<>();
        Thread producent = new Producent(blockingQueue);
        Thread konsument = new Konsument(blockingQueue);
        producent.start();
        konsument.start();
    }
}

我做错了什么?我还尝试了ArrayBlockingQueue和LinkedBlockingQueue。

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2021-05-08 01:18:58

上下文切换可以在任何地方发生,在这里它们可以防止日志消息被及时写入。假设你的消费者从队列中取出了一些东西,这通知了另一个线程,它可以在消费者执行println之前把一些东西放进去。上下文切换落在队列take之后和println之前。这些方法调用是否是同一语句的一部分并不重要,当队列的方法调用完成时,队列将放弃其锁。

但是您会说,“是的,但是另一个线程也会导致通知,这不是应该导致另一个上下文切换吗?”上下文切换不是强制的,它们取决于操作系统,它可以使用线程,也可以不使用线程。它可能决定要最大限度地减少交换机的数量。

对于生产者来说,println是第一位的。但是你不需要通知上下文切换,它可以在任何时候发生。

您可以尝试让两个线程在循环内的共享队列上进行同步:

代码语言:javascript
复制
for (int i = 0; i < 100; i++) {
    synchronized (blockingQueue) {
        consume(blockingQueue.take());
    }
}

(我只显示了一个线程,但两个线程都需要更改才能获得相同的锁。)

这将确保println反映队列中最近发生的事情。

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

https://stackoverflow.com/questions/67439052

复制
相关文章

相似问题

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