Очередь блокировки не работает в java, я могу поместить больше элементов, чем заданный размер очереди блокировки - PullRequest
0 голосов
/ 13 июля 2020

Я объявил BlockingQueue размером 1

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 и StackOverflow безуспешно.

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

Ответы [ 2 ]

2 голосов
/ 13 июля 2020

Измените печать на

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);

, и вы увидите, что они на самом деле печатаются не в правильном временном порядке

1 голос
/ 13 июля 2020

Это просто состояние гонки между обоими потоками.

Вы полагаете, что оно произвело второе сообщение , потому что вы видите вывод производителя раньше, чем получателя . Ему повезло, и его System.out был обработан раньше, чем пользовательский.

Попробуйте отладить его, и вы увидите, что второй элемент не добавляется, пока потребитель не прочитает первый. Не верьте порядку в выходах консоли ...

...