阻塞队列在 java 中不起作用,我可以放置比阻塞队列定义的大小更多的元素

Blocking queue not working in java, I can put more element than the defined size of blocking queue

我已经声明了一个大小为 1 的 BlockingQueue

final BlockingQueue<Integer> blockingQueue = new ArrayBlockingQueue<Integer>(1);.

但我可以向队列中添加 1 个以上的元素。我确定我在这方面遗漏了一些东西,比如这是 BlockingQueue 的核心 属性。这是来自 java 文档的代码。

    /**
     * Creates an {@code ArrayBlockingQueue} with the given (fixed)
     * capacity and default access policy.
     *
     * @param capacity the capacity of this queue
     * @throws IllegalArgumentException if {@code capacity < 1}
     */
    public ArrayBlockingQueue(int capacity) {
        this(capacity, false);
    }

但是当我实施时,我能够产生超过 1 个元素,根据我的说法,如果 BlockingQueue 的大小为 1,那么在产生 1 个元素之后,它应该等待消费者使用该元素。 这是代码和代码的输出。

我需要一个解释,你能帮我解决这个问题吗?

我已经尝试 google 搜索和 Whosebug 但没有成功。

import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

public class BlockingQueueTestWorking {

    public static void main(String[] args) {
        final BlockingQueue<Integer> blockingQueue = new ArrayBlockingQueue<Integer>(1);

        Runnable producer = () -> {
            try {
                int iterator = 0;
                while (true) {
                    if (iterator++ == 10)
                        break;

                    String name = Thread.currentThread().getName();
                    Integer i = (int) (Math.random() * 10);
                    blockingQueue.put(i);
                    System.out.println(name + " Producing:-> " + i);
                }
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        };

        Runnable consumer = () -> {
            try {
                int iterator = 0;
                while (true) {
                    if (iterator++ == 10)
                        break;
                    String name = Thread.currentThread().getName();
                    Integer take = blockingQueue.take();
                    System.out.println(name + " Consuming:<- " + take);
                }
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        };

        Thread threadProducer = new Thread(producer);


        final ExecutorService executor = Executors.newFixedThreadPool(10);
        executor.execute(threadProducer);
        
        Thread threadConsumer = new Thread(consumer);
        executor.execute(threadConsumer);

        executor.shutdown();
    }

}

Output:
pool-1-thread-1 Producing:-> 2
pool-1-thread-1 Producing:-> 7
pool-1-thread-2 Consuming:<- 2
pool-1-thread-2 Consuming:<- 7
pool-1-thread-1 Producing:-> 6
pool-1-thread-2 Consuming:<- 6
pool-1-thread-1 Producing:-> 2
pool-1-thread-2 Consuming:<- 2
pool-1-thread-1 Producing:-> 6
pool-1-thread-2 Consuming:<- 6
pool-1-thread-1 Producing:-> 1
pool-1-thread-2 Consuming:<- 1
pool-1-thread-1 Producing:-> 2
pool-1-thread-2 Consuming:<- 2
pool-1-thread-1 Producing:-> 2
pool-1-thread-2 Consuming:<- 2
pool-1-thread-1 Producing:-> 2
pool-1-thread-2 Consuming:<- 2
pool-1-thread-1 Producing:-> 4
pool-1-thread-2 Consuming:<- 4

这只是两个线程之间的竞争条件。

您认为它产生了第二条消息因为您在消费者一条消息之前看到了生产者的输出。很幸运,他的 System.out 在消费者的之前得到处理。

尝试对其进行调试,您会发现在消费者阅读第一个元素之前没有添加第二个元素。 不要相信控制台输出中的顺序...

将打印更改为

System.out.println(String.format("[%s]", new Timestamp(System.currentTimeMillis())) + " Producing:-> " + i);

System.out.println(String.format("[%s]", new Timestamp(System.currentTimeMillis())) + name + " Consuming:<- " + take);

你会发现它们实际上没有按正确的时间顺序打印