我希望有一个环形缓冲区队列,它将接收对象并将它们分布在线程池中的多个线程中,在单个生产者中分配给多个消费者方式。如何使用disruptor模式实现这一目标?任何HelloDemux
代码示例?感谢!!!
答案 0 :(得分:6)
这个article详细介绍了实现disruptor模式的解复用器的所有内容,但我认为线程池意味着你需要一个与disruptor模式相反的调度程序。要实现demux,您需要设置固定数量的使用者线程,而不是池,并让它们从队列尾部获取消息。 现在,您可能会问,如果没有调度员,他们怎么能这样做呢?他们只是忙着旋转(或使用其他一种等待策略,即旋转,屈服,停车,睡眠等组合。 )在队列尾巴周围。 现在,您可能会问,他们怎么能在不相互衔接的情况下做到这一点?那么您有两个选择:您可以使用MODULUS(无锁)或CAS(轻锁)。每个人都有自己的优点和缺点。 MODULUS很快,但如果一个消费者落后,可能会引起车道争用。 CAS不是那么快,但不会引起车道争用。
package com.coralblocks.coralqueue.sample.demux;
import com.coralblocks.coralqueue.demux.CASAtomicDemux;
import com.coralblocks.coralqueue.demux.Demux;
public class Sample {
private static final int NUMBER_OF_CONSUMERS = 4;
public static void main(String[] args) throws InterruptedException {
final Demux<StringBuilder> queue = new CASAtomicDemux<StringBuilder>(1024, StringBuilder.class, NUMBER_OF_CONSUMERS);
Thread[] consumers = new Thread[NUMBER_OF_CONSUMERS];
for(int i = 0; i < consumers.length; i++) {
final int index = i;
consumers[i] = new Thread() {
@Override
public void run() {
boolean running = true;
while(running) {
long avail;
while((avail = queue.availableToPoll(index)) == 0); // busy spin
for(int i = 0; i < avail; i++) {
StringBuilder sb = queue.poll(index);
if (sb == null) break; // mandatory for demuxes!
if (sb.length() == 0) {
running = false;
break; // exit immediately...
} else {
System.out.println(sb.toString());
}
}
queue.donePolling(index);
}
}
};
consumers[i].start();
}
StringBuilder sb;
for(int i = 0; i < 10; i++) {
while((sb = queue.nextToDispatch()) == null); // busy spin
sb.setLength(0);
sb.append("message ").append(i);
queue.flush();
}
// send a message to stop consumers...
for(int i = 0; i < NUMBER_OF_CONSUMERS; i++) {
// because the consumer exit immediately on this message, each
// consumer will get one of these messages and exit...
while((sb = queue.nextToDispatch()) == null); // busy spin
sb.setLength(0);
}
queue.flush(); // sent batch
for(int i = 0; i < consumers.length; i++) consumers[i].join();
}
}