LinkedBlockingQueue的内部工作

时间:2018-07-05 17:03:41

标签: java concurrency

我想知道如何处理以下情况:

  • ScheduledThreadPool一次生成N个元素,每秒。
  • 热切的消费者,它试图从队列中创建N个对象的批次,而不是一个一个地处理。

当生产者醒来并开始将元素放入队列(仅从列表中传输对象)时,让我们一次假设100个元素,消费者将立即唤醒,在生产者将100个元素放入队列之前清空队列元素?

还是我可以期望消耗线程的休眠时间更长?

2 个答案:

答案 0 :(得分:0)

LinkedBlockingQueue对其所有操作都使用单锁(ReentrantLock)。

在您的情况下,如果您一次说100个元素,则意味着调用put方法100次。 put方法尝试在插入之前先获取锁。因此,很有可能给消费者线程一个机会,并且可能耗尽队列。

LBQ还使用非公平锁定,因此很可能发生饥饿。

答案 1 :(得分:0)

感谢@Neerav 我做了一点测试

private static void raceforIntegers() {
    BlockingDeque<Integer> q = new LinkedBlockingDeque<>();

    ScheduledExecutorService ex = Executors.newSingleThreadScheduledExecutor();
    // Delay producer 1 sec, so consumer always waits at 1st 
    ex.scheduleAtFixedRate(() -> {
                if (q.isEmpty()) {
                    Stream.iterate(0,  i -> ++i)
                            .limit(10)
                            .forEach(q::add);
                } else {
                    ex.shutdown();
                }
            }, 1L, 1L, TimeUnit.SECONDS);


    consumeIntegers(q);
}

private static void consumeIntegers(BlockingDeque<Integer> q) {
    int elememts = 30;
    StringBuilder sb = new StringBuilder();
    do {
        try {
            int n = q.take();
            int s = q.size();
            sb.append(s + ":::::" + n + "\n");
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    } while (elememts-- > 0);
    System.out.println(sb);
}

输出

Size  Num
1:::::0
8:::::1
7:::::2
6:::::3
5:::::4
4:::::5
3:::::6
2:::::7
1:::::8
0:::::9

5:::::0
8:::::1
7:::::2
6:::::3
5:::::4
4:::::5
3:::::6
2:::::7
1:::::8
0:::::9

3:::::0
7:::::1
7:::::2
6:::::3
5:::::4
4:::::5
3:::::6
2:::::7
1:::::8
0:::::9
9:::::0