Java 阻塞队列

标签 java multithreading

<分区>

我将 BQ 的初始容量设置为 3。但有时生产者会超出初始容量。请引用输出。

问题更新: ArrayBlockingQueue 使用显式锁来保证线程安全,但在代码中我获取了 sharedResource 对象的监视器/隐式锁。

如何将 System.out.println("Produce : "+d); 作为同一个显式锁的一部分?/如何使用相同的 BQ 锁实现打印 BQ 内部内容的预期输出?

声明

BlockingQueue<String> sharedResource = new ArrayBlockingQueue<String>(3);

制作人

Runnable r = new Runnable() {
    public void run() {
        for (int i = 1; i <= 2; i++) {
            try {

                String d = Thread.currentThread().getName() + "->" + i;
                synchronized (sharedResource) {
                    sharedResource.put(d);
                    System.out.println("Produce : " + d);
                }
                Thread.sleep(100);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
};

消费者

Thread consumer = new Thread(new Runnable() {
    public void run() {
        while (true) {

            try {
                System.out.println("C : " + sharedResource.take());
                Thread.sleep(100);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
});

输出

***P1->1
P3->1
P5->1
P2->1***
C : P1->1
C : P3->1
P4->1
C : P5->1
P2->2
P5->2
C : P2->1
P3->2
C : P4->1
P1->2
C : P2->2
P4->2
C : P5->2
C : P3->2
C : P1->2
C : P4->2

更新:我调用生产者和消费者如下。

Thread producer1 = new Thread(r);
Thread producer2 = new Thread(r);
Thread producer3 = new Thread(r);
Thread producer4 = new Thread(r);
Thread producer5 = new Thread(r);

producer1.setName("P1");
producer2.setName("P2");
producer3.setName("P3");
producer4.setName("P4");
producer5.setName("P5");

producer1.start();
producer2.start();
producer3.start();
producer4.start();
producer5.start();

consumer.start();

最佳答案

答案在 ArrayBlockingQueue#take() 方法中非常简单

http://docs.oracle.com/javase/7/docs/api/java/util/concurrent/ArrayBlockingQueue.html#take()

当您调用 take 时,它​​表示“检索并删除此队列的头部,必要时等待直到元素可用。” 所以它将队列大小减少 1 所以 考虑 1. 队列中有 4 个元素 2. 你调用 take() 3.队列大小将减少到3

因此,在您的情况下,您的队列不会超过 3 的大小。 您同时从队列中放入和删除值,因此队列大小不超过 3 但是,如果您通过 Thread.sleep(500) 减慢消费者的速度;您将获得所需的输出。

关于Java 阻塞队列,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/24007043/

相关文章:

Java - 将 paintComponent 用于图形,从内部调用函数?

c# - 如何对这个库进行单元测试?

C#多线程查询

java - 如何用Java将控制台输出写入Excel文件

c# - 从另一个线程更新 ObservableCollection 的最佳方法是什么?

java - VolatileImage 是线程安全的吗?

multithreading - x86 CPU 会重新排序指令吗?

JavaFX 11 : IllegalAccessError when creating Label

java - @Header 注释未按预期工作

java - 相等检查后使用 Long 的 NullPointerException