DISRUPTOR初步介绍
队列底层一般分为三种:数组、链表、堆(不讨论)
基于数组线程安全的队列,典型是ArrayBlockingQueue,通过加锁的方式
来保证线程安全。基于链表线程安全队列分为LinkedBlockingQueue和
ConcurrentLinkedQueue。 前者通过加锁方式实现线程安全,后者通过
原子变量CAS来实现
通过不加锁的方式实现的队列都是无界的,而加锁的方式可以实现有界队列。
在稳定性要求高的系统中,为了防止生产者速度过快,导致内存溢出,只能
选择有界队列。同时为了减少Java垃圾回收堆系统性能的影响,尽量选择
array/heap数据结构,这些符合条件只有ArrayBlockingQueue
ArrayBlockingQueue在实际使用过程中,因加锁和伪共享(无法充分
使用缓存行特性的现象)等出现严重性能问题
Disruptor设计
环形数组结构
为了避免垃圾回收,采用数组而非链表。同时数组处理器的缓存机制更加友好
元素位置定位
数组长度2^n,通过位运算,加快定位的速度,下标采用递增的形式。index
是long类型
无锁设计
每个生产者活着消费者线程,会先申请可以操作的元素在数组中的位置,申请
到之后,直接在该位置写入或者读取数据
使用Disruptor每10秒向disruptor插入一个元素,消费者读取并打印示例
public class DisruptorMain {
public static void main(String[] args) throws Exception {
class Element {
private int value;
public int get() {
return value;
}
public void set(int value) {
this.value = value;
}
}
ThreadFactory threadFactory = new ThreadFactory() {
@Overrid
public Thread newThread(Runnable r) {
return new Thread(r, "thread-1")
}
};
EventFactory<Element> factory = new EveentFactory<Element>() {
@Overrid
public Element newInstance() {
return new Element();
}
};
EventHandler<Element> handler = new EventHandler<Element>() {
@Override
public void onEvent(Element element, long sequence, boolean endOfBatch) {
Systtem.out.println("element" + element.get());
}
};
BlockingWaitStrategy strategy = new BlockingWaitStrategy();
int bufferSize = 16;
Disruptor<Element> disruptor = new Disruptor(factory, bufferSize,
threadFactory, ProducerType.SINGLE, strategy);
disruptor.handleEventsWith(handler);
disruptor.start();
RingBuffer<Element> ringBuffer = disruptor.getRingBuffer();
for(int l = 0; true; l++) {
long sequence = ringBuffer.next();
try{
Element e = ringBuffer.get(sequence);
e.set(l);
}finally {
ringBuffer.publish(sequence);
}
Thread.sleep(10);
}
}
}
内容来源于美团技术博客