简体   繁体   English

ArrayBlockingQueue+在 java 中同步

[英]ArrayBlockingQueue+synchronized in java

I use ArrayBlockingQueue in my code and it has any element.我在我的代码中使用 ArrayBlockingQueue 并且它有任何元素。 But threads calls to take method.但是线程调用采取方法。 why?为什么? I think put method before take method should called.我认为应该先调用 put 方法,然后再调用 take 方法。 sorry for the bad writing.抱歉写得不好。

How do you know it isn't blocking until an item is available?你怎么知道在一个项目可用之前它不会阻塞?

You should log the item that is removed from the queue as well.您还应该记录从队列中删除的项目。 And ideally include some Id that helps identify unique values such as the thread name when you put.理想情况下,包括一些有助于识别唯一值的 Id,例如您放置时的线程名称。

Remember the methods on the queue are atomic, your logging is not, so it might happen out of order in comparison to the events you are trying to debug.请记住,队列中的方法是原子的,而您的日志记录不是,因此与您尝试调试的事件相比,它可能会出现乱序。

To make this more obvious, I would adding logging before the blocking methods that show which threads are waiting.为了使这一点更明显,我将在显示哪些线程正在等待的阻塞方法之前添加日志记录。

I also save something so it is easy to see where the message taken has come from.我还保存了一些内容,以便轻松查看所获取的消息来自何处。 This way you can see that the methods are blocking and working as expected.通过这种方式,您可以看到这些方法正在阻塞并按预期工作。

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

public class ArrayBlockingQueueExample {
    public static void main(String[] args) {
        ArrayBlockingQueue<String> blockingQueue = new ArrayBlockingQueue<>(3);
        Thread[] threads = {
            new Producer(blockingQueue),
            new Producer(blockingQueue),
            new Producer(blockingQueue),
            new Producer(blockingQueue),
            new Producer(blockingQueue),
            new Consumer(blockingQueue),
            new Consumer(blockingQueue),
            new Consumer(blockingQueue),
            new Consumer(blockingQueue),
            new Consumer(blockingQueue),
        };

        for(Thread t: threads) {
            t.start();
        }
    }

    static class Consumer extends Thread {
        private final BlockingQueue<String> queue;

        Consumer(BlockingQueue<String> queue) {
            this.queue = queue;
        }

        @Override
        public void run() {
            try {
                System.out.println("Consumer:" + this.getName() + " waiting... ");
                String takenValue = queue.take();
                // Logging here may occur out of order in comparison with the producer thread logging.
                System.out.println("Consumer:" + this.getName() + " received: " + takenValue);
            } catch (InterruptedException e) {
                // Reset the interrupted flag on the thread.
                Thread.currentThread().interrupt();
                e.printStackTrace();
            }
        }
    }

    static class Producer extends Thread {
        private final BlockingQueue<String> queue;

        Producer(BlockingQueue<String> queue) {
            this.queue = queue;
        }

        @Override
        public void run() {
            try {
                String putValue = "Producer:" + this.getName() + " says hello!";
                System.out.println("Producer:" + this.getName() + " waiting... ");
                queue.put(putValue);
                // Logging here may occur out of order in comparison with the consumer thread logging.
                System.out.println("Producer:" + this.getName() + " sent: " + putValue);
            } catch (InterruptedException e) {
                // Reset the interrupted flag on the thread.
                Thread.currentThread().interrupt();
                e.printStackTrace();
            }
        }
    }
}

With this code you will see something like the following output:使用此代码,您将看到类似于以下 output 的内容:

Consumer:Thread-5 waiting... 
Consumer:Thread-7 waiting... 
Producer:Thread-1 waiting... 
Producer:Thread-0 waiting... 
Producer:Thread-4 waiting... 
Consumer:Thread-9 waiting... 
Consumer:Thread-8 waiting... 
Consumer:Thread-6 waiting... 
Producer:Thread-2 waiting... 
Producer:Thread-3 waiting... 
Consumer:Thread-6 received: Producer:Thread-0 says hello!
Producer:Thread-2 sent: Producer:Thread-2 says hello!
Consumer:Thread-5 received: Producer:Thread-3 says hello!
Producer:Thread-1 sent: Producer:Thread-1 says hello!
Consumer:Thread-7 received: Producer:Thread-4 says hello!
Consumer:Thread-8 received: Producer:Thread-1 says hello!
Producer:Thread-3 sent: Producer:Thread-3 says hello!
Producer:Thread-4 sent: Producer:Thread-4 says hello!
Consumer:Thread-9 received: Producer:Thread-2 says hello!
Producer:Thread-0 sent: Producer:Thread-0 says hello!

Notice that the consumer (Thread-6) received hello from the Thread-0 producer in the first line of logging, but the sent logging from Thread-0 is the last line logged?请注意,消费者(Thread-6)在第一行日志记录中收到了来自 Thread-0 生产者的 hello,但是从 Thread-0 sent的日志记录是记录的最后一行? This order has nothing to do with the sequence of put events on the blocking queue.此顺序与阻塞队列上的 put 事件顺序无关。

It doesn't matter what order put() and take() are executed - the effect is the same, because they are blocking calls.执行put()take()的顺序无关紧要 - 效果是一样的,因为它们是阻塞调用。

take() takes and returns the next item, waiting for one if none are available. take()获取并返回下一个项目,如果没有可用则等待一个。

put() adds an item, waiting for one to be taken if no space is available. put()添加一个项目,如果没有可用空间,则等待一个项目被占用。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM