본문 바로가기

공부/Java

[LMAX-Exchange/disruptor] ringbuffer 사용하기

LMAX Disruptor

A High Performance Inter-Thread Messaging Library

Disruptor의 목적

동일 프로세스 내, 스레드 간의 데이터(메시지, 이벤트 등..)를 이동시키는 것

사용법

기본예제 수정하여 테스트 진행

메이븐 디펜던시

<dependency>
    <groupId>com.lmax</groupId>
    <artifactId>disruptor</artifactId>
    <version>3.2.0</version>
</dependency>

ValueEvent.class

@Getter @Setter
public class ValueEvent {
    private String value;

    public final static EventFactory<ValueEvent> EVENT_FACTORY = new EventFactory<ValueEvent>() {
        @Override
        public ValueEvent newInstance() {
            // TODO Auto-generated method stub
            return new ValueEvent();
        }
    };
}

RingBufferService.class

@Slf4j
@Service
public class RingBufferService {

    private ExecutorService exec;
    private Disruptor<ValueEvent> disruptor;
    private RingBuffer<ValueEvent> ringBuffer;

    @SuppressWarnings("unchecked")
    @PostConstruct
    public void init() {
        log.info("<init>");
        exec = Executors.newFixedThreadPool(1);
        disruptor = new Disruptor<>(ValueEvent.EVENT_FACTORY, 1024, exec);
        disruptor.handleEventsWith(eventHandler);
        ringBuffer = disruptor.start();

    }

    @PreDestroy
    public void destroy() {
        log.info("<destroy>");
        if(disruptor != null) {
            disruptor.shutdown();
        }
        if(exec != null) {
            exec.shutdown();
        }
    }

    private EventHandler<ValueEvent> eventHandler = new EventHandler<ValueEvent>() {
        @Override
        public void onEvent(ValueEvent event, long sequence, boolean endOfBatch) throws Exception {
            // TODO Auto-generated method stub
            log.info("<value> Sequence : {} / ValueEvent : {}", sequence, event.getValue());
        }
    };

    public void putToRingBuffer(ValueEvent event) {
        long seq;
        try {
            seq = ringBuffer.tryNext();
            ringBuffer.get(seq).setValue(event.getValue());
            ringBuffer.publish(seq);
        } catch (InsufficientCapacityException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }
}

ScheduleConfig.class

@Component
public class ScheduleConfig {

    @Autowired
    private RingBufferService ringBufferService;

    @Scheduled(cron="3/5 * * * * *")
    public void ringBufferTest() {
        ValueEvent event = new ValueEvent();
        for(int i=0 ; i<10 ; i++) {
            String uuid = UUID.randomUUID().toString();
            event.setValue(uuid);
            ringBufferService.putToRingBuffer(event);
        }
    }
}

참고

LMAX github : https://github.com/LMAX-Exchange/disruptor
번역1 : https://box0830.tistory.com/197
번역2 : https://krksap.tistory.com/1239
LMAX Architecture 와 Distruptor 패턴 : https://okky.kr/article/465087

'공부 > Java' 카테고리의 다른 글

sigar 라이브러리  (0) 2019.08.06
Apache POI 사용한 엑셀 파일 생성  (0) 2019.07.10
Optional 사용하여 null 해결하기  (0) 2019.03.03
NIO ??  (0) 2019.02.10