【发布时间】:2018-01-07 18:38:59
【问题描述】:
我已经创建了一个与具有 20 个核心的指定线程池的连接。
ConnectionFactory factory = new ConnectionFactory();
....
//specified es
ExecutorService consumerExecutor = Executors.newFixedThreadPool(threadNum, threadFactory);
con = factory.newConnection(consumerExecutor, addresses);
然后从此连接创建一个通道:
final Channel channel = connection.createChannel();
并使用它来创建一个 DefaultConsumer。
虽然我发现虽然线程可以用来消费消息,但始终只有一个线程在消费消息,即使消息在服务器中大量积累。
我查看源代码并找到:
private final class WorkPoolRunnable implements Runnable {
@Override
public void run() {
int size = MAX_RUNNABLE_BLOCK_SIZE;
List<Runnable> block = new ArrayList<Runnable>(size);
try {
Channel key = ConsumerWorkService.this.workPool.nextWorkBlock(block, size);
if (key == null) return; // nothing ready to run
try {
for (Runnable runnable : block) {
runnable.run();
}
} finally {
if (ConsumerWorkService.this.workPool.finishWorkBlock(key)) {
ConsumerWorkService.this.executor.execute(new WorkPoolRunnable());
}
}
} catch (RuntimeException e) {
Thread.currentThread().interrupt();
}
}
}
/* Basic work selector and state transition step */
private K readyToInProgress() {
K key = this.ready.poll();
if (key != null) {
this.inProgress.add(key);
}
return key;
}
/**
* Return the next <i>ready</i> client,
* and transfer a collection of that client's items to process.
* Mark client <i>in progress</i>.
* If there is no <i>ready</i> client, return <code><b>null</b></code>.
* @param to collection object in which to transfer items
* @param size max number of items to transfer
* @return key of client to whom items belong, or <code><b>null</b></code> if there is none.
*/
public K nextWorkBlock(Collection<W> to, int size) {
synchronized (this) {
K nextKey = readyToInProgress();
if (nextKey != null) {
VariableLinkedBlockingQueue<W> queue = this.pool.get(nextKey);
drainTo(queue, to, size);
}
return nextKey;
}
}
诀窍应该在ConsumerWorkService.this.workPool.nextWorkBlock,它从就绪队列中轮询通道,并在运行回调run() 后添加到完成块中的读取队列。如果我错了,请纠正我。
这很令人困惑,因为消费者绑定到一个通道,并且在最后一个任务块完成之前,通道不会释放到队列中,这意味着线程池始终只为该消费者提供一个线程。
问题:
- 为什么 RabbitMQ 设计这个模型
- 我们如何优化这个问题
- 是否可以将任务提交到
handleDelivery中的独立线程池以消费消息以及确认(确保仅在任务完成后确认消息)
【问题讨论】:
标签: java multithreading rabbitmq