【问题标题】:Does a Synchronous Queue create a thread on each offer/put?同步队列是否在每个报价/报价上创建一个线程?
【发布时间】:2013-08-27 20:55:20
【问题描述】:

我无法理解 Synchronous Queue 的工作原理。
我理解这个想法是任务的移交是直接给线程的,但构造函数没有限制,例如像其他 API 那样的最大线程数。
因此,当 putoffer 完成时,它本质上是否传递给另一个线程?
所以,如果我这样做,例如100 put 会被传递给 100 个线程吗?
我试图阅读源代码,但无法弄清楚发生了什么。它似乎创建了一个节点的链接列表,其中每个节点都封装了一个线程,但是这个列表是如何维护的,例如扩展/收缩等以及踏板如何运行任务对我来说并不清楚。
那么这个列表会随着我们提供任务而扩展吗?因此消费者线程(服务员)不断增加?
这些是否被重复使用?或者只是执行某些操作然后停止?

【问题讨论】:

    标签: java multithreading concurrency queue java.util.concurrent


    【解决方案1】:

    听起来你误解了SynchronousQueue的目的。

    SynchronousQueue 不创建任何线程。 当您调用 put 时,put 不会完成,直到另一个线程(您创建的线程)将该元素从 SynchronousQueue 中取出。

    “如果我这样做,例如 100 put”如果你有一百个线程,每个线程都在同一个 SynchronousQueue 上调用 put,那么所有这些线程将等待直到其他线程开始 take 这些元素离开。如果你有一个线程,它一次只会执行一个put,并且每次它都会等待另一个线程获取该元素,然后再添加另一个。

    内部使用的列表是一个链表,它像链表一样扩展并获得 GC 处理。

    【讨论】:

    • 如果我的一个线程获取了另一个线程放入的数据,那么链表需要什么?
    • 需要的是你可能有 100 个线程,每个线程都有一个等待被占用的元素。
    • 那么,如果我有X 需要处理此队列的线程数,我该如何根据负载调整X 数? IE。相应地增加/减少它们?
    • 在这种情况下,SynchronousQueue 可能实际上不是您想要的数据结构——也许您应该将它们作为任务提交给Executors.newCachedThreadPool,而不是将您的对象放入队列中。
    【解决方案2】:

    我理解这个想法是任务的移交是给线程的 直接但构造函数没有限制,例如最大数量 与其他 API 类似的线程。

    队列实现的构造函数中的所有 int 参数中的第一个是SIZE,而不是线程数。

    那么这个列表是否会随着我们提供任务而扩展?结果 消费者线程(服务员)不断增加?

    同步队列用于切换目的。来自生产者的put() 调用将阻塞,直到队列中有一个消费者执行take()。这与线程数无关。消费者线程不一定要增加。一旦消费者处理完一条消息,它就可以再次从队列中执行 take()。

    public class MyWorker extends Thread {
        private final BlockingQueue<String> queue;
        public MyWorker(BlockingQueue<String> queue) {
            this.queue = queue;
        }
    
        public void run() {
            try {
                while ( true ) {
                    String s = queue.take();
                    doWork(s);
                }
            }
            catch ( InterruptedException ie ) { 
                // just terminate
            }
        }
    }
    
    public class SyncQueueExample {
        // …    
        public SyncQueueExample() {
            try {
                int workItem = 0;
                // Create a synchronous queue
                BlockingQueue<String> queue = new SynchronousQueue<String>();
    
                // Create the child worker thread
                MyWorker worker = new MyWorker(queue);
                worker.start();
    
                // Start sending to the queue
                while ( true ) {
                    System.out.println("\nPlacing work on queue");
                    String work = "Work Item:" + (++workItem);
                    queue.put(work);
                }
            }
            catch ( Exception e ) {
                e.printStackTrace();
            }
        }
    }
    

    输出:运行时,队列生产者和消费者之间的输出将是“协调的”,实际上是交替的:

    Placing work on queue
    Thread 'Thread-1' processing work: Work Item:1
    
    Placing work on queue
    Thread 'Thread-1' processing work: Work Item:2
    
    Placing work on queue
    Thread 'Thread-1' processing work: Work Item:3
    
    Placing work on queue
    Thread 'Thread-1' processing work: Work Item:4
    

    更多关于Synchronous Queue

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2013-08-12
      • 1970-01-01
      • 2011-03-01
      • 1970-01-01
      • 1970-01-01
      • 2011-06-23
      • 2013-04-08
      • 1970-01-01
      相关资源
      最近更新 更多