使用Disruptor實現生產者和消費者模型

lonecloud發表於2018-05-07

生產者

package cn.lonecloud.procum.disruptor;

import cn.lonecloud.procum.Data;
import com.lmax.disruptor.RingBuffer;

import java.nio.ByteBuffer;

/**
 * @author lonecloud
 * @version v1.0
 * @date 下午3:02 2018/5/7
 */
public class Producer {

    //佇列
    private final RingBuffer<Data> dataRingBuffer;

    public Producer(RingBuffer<Data> dataRingBuffer) {
        this.dataRingBuffer = dataRingBuffer;
    }

    /**
     * 插入資料
     * @param s
     */
    public void pushData(String s) {

        //獲取下一個位置
        long next = dataRingBuffer.next();
        try {
            //獲取容器
            Data data = dataRingBuffer.get(next);
            //設定資料
            data.setData(s);
        } finally {
            //插入
            dataRingBuffer.publish(next);
        }
    }
}

  消費者

package cn.lonecloud.procum.disruptor;

import cn.lonecloud.procum.Data;
import com.lmax.disruptor.WorkHandler;

/**
 * @author lonecloud
 * @version v1.0
 * @date 下午3:01 2018/5/7
 */
public class Customer implements WorkHandler<Data> {
    @Override
    public void onEvent(Data data) throws Exception {
        System.out.println(Thread.currentThread().getName()+"---"+data.getData());
    }
}

  資料工廠

package cn.lonecloud.procum.disruptor;

import cn.lonecloud.procum.Data;
import com.lmax.disruptor.EventFactory;

/**
 * @author lonecloud
 * @version v1.0
 * @date 下午3:02 2018/5/7
 */
public class DataFactory implements EventFactory<Data> {

    @Override
    public Data newInstance() {
        return new Data();
    }
}

  主函式

package cn.lonecloud.procum.disruptor;

import cn.lonecloud.procum.Data;
import com.lmax.disruptor.RingBuffer;
import com.lmax.disruptor.dsl.Disruptor;

import java.util.UUID;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

/**
 * @author lonecloud
 * @version v1.0
 * @date 下午3:09 2018/5/7
 */
public class Main {
    public static void main(String[] args) throws InterruptedException {
        //建立執行緒池
        ExecutorService service = Executors.newCachedThreadPool();
        //建立資料工廠
        DataFactory dataFactory = new DataFactory();
        //設定緩衝區大小,必須為2的指數,否則會有異常
        int buffersize = 1024;
        Disruptor<Data> dataDisruptor = new Disruptor<Data>(dataFactory, buffersize,
                service);
        //建立消費者執行緒
        dataDisruptor.handleEventsWithWorkerPool(
                new Customer(),
                new Customer(),
                new Customer(),
                new Customer(),
                new Customer(),
                new Customer(),
                new Customer()
        );
        //啟動
        dataDisruptor.start();
        //獲取其佇列
        RingBuffer<Data> ringBuffer = dataDisruptor.getRingBuffer();
        for (int i = 0; i < 100; i++) {
            //建立生產者
            Producer producer = new Producer(ringBuffer);
            //設定內容
            producer.pushData(UUID.randomUUID().toString());
            //Thread.sleep(1000);
        }
    }
}

  其中策略有幾種:

1. BlockingWaitStrategy:阻塞策略,最節省CPU,但是高併發條件下效能最糟糕

2 SleepingWaitStrategy:在迴圈中無限等待,處理資料會產生高延遲,對生產執行緒影響小,場景:非同步日誌

3. YieldingWaitStrategy:低延遲場合,使用必須保證剩餘的消費者執行緒的邏輯CPU

4. BusySpinWaitStrategy:消費者執行緒會盡最大努力瘋狂的監控緩衝區變化。

相關文章