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);
	}
}

}

内容来源于美团技术博客

posted @ 2022-08-03 17:16  秋水秋色  阅读(60)  评论(0编辑  收藏  举报