高并发下,实现双缓存分组锁

近期看了一篇文章,关于高并发下通过双缓存分组锁去提高服务并发能力。

双缓存:双缓存的目的是,如果单缓冲区满的时候,需要同步把缓冲的数据刷进磁盘,这个过程需要等很久,这妨碍到了程序的效率。通过双缓存,当某一个缓冲满了的时候,切换成另一个缓冲区,满的缓冲去可以慢慢去磁盘写数据。

文档地址:https://mp.weixin.qq.com/s/d4qfu2MxESc1YJV4Ud5mnA

自己写了个小例子(代码不足,望大侠们指点),测试过后,效率是有质的飞跃。

上图为最终的实现方案,用的是别人的图。

import org.sean.framework.pool.ExecutorPool;
import org.sean.framework.util.NumberUtil;

import java.nio.DoubleBuffer;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.CountDownLatch;

/**
 * 实现双缓存分组锁
 */
public class DoubleBufferTest {

    /**
     * 单缓存
     */
    private static final Map<Integer, DoubleBuffer> doubleBufferMap = new HashMap<>();
    /**
     * 分组数量
     */
    private static final int size = 1000;

    /**
     * 每个分组设置空间大小
     */
    private static final int doubleSize = 100;

    /**
     * 爽缓存
     */
    private static final Map<Integer, DoubleBufferBeanMap> doubleBuffer2Map = new HashMap<>();


    static {
        //分组操作
        for (int i = 0; i < size; i++) {
            doubleBufferMap.put(i, DoubleBuffer.allocate(doubleSize));
            doubleBuffer2Map.put(i, new DoubleBufferBeanMap());
        }
    }

    public static void main(String[] args) throws Exception {
        int num = 100000;
        //单缓存分组锁实现
//        long t0 = System.currentTimeMillis();
//        CountDownLatch count1 = new CountDownLatch(num);
//        for (int i = 0; i < num; i++) {
//            ExecutorPool.getInstance().execute(() -> {
//                DoubleBuffer doubleBuffer = getRandomDoubleBuffer();
//                try {
//                    synchronized (doubleBuffer) {
//                        if (isNotFull(doubleBuffer)) {
//                            task(doubleBuffer);
//                        }
//                        if (!isNotFull(doubleBuffer)) {
//                            flush(doubleBuffer);
//                        }
//                    }
//                } catch (InterruptedException e) {
//                    e.printStackTrace();
//                } finally {
//                    count1.countDown();
//                }
//
//            });
//        }
//        count1.await();
//        long t1 = System.currentTimeMillis();
//        System.out.println("单缓存===========>" + (t1 - t0));

        //双缓存分组锁实现
        long t4 = System.currentTimeMillis();
        CountDownLatch count3 = new CountDownLatch(num);
        for (int i = 0; i < num; i++) {
            ExecutorPool.getInstance().execute(() -> {
                DoubleBufferBeanMap map = getRandomDoubleBufferMap();
                DoubleBuffer doubleBuffer;
                try {
                    synchronized (map) {
                        doubleBuffer = map.get();
                        if (isNotFull(doubleBuffer)) {
                            task(doubleBuffer);
                        }
                        if (!isNotFull(doubleBuffer)) {
                            map.slide();
                        }
                    }
                    if (!isNotFull(doubleBuffer)) {
                        map.flush(doubleBuffer);
                    }
                } catch (InterruptedException e) {
                    System.out.println(map);
                    e.printStackTrace();
                } finally {
                    count3.countDown();
                }

            });
        }
        count3.await();
        long t5 = System.currentTimeMillis();
        System.out.println("双缓存===========>" + (t5 - t4));


    }

    /**
     * 随机获取一个buffer
     *
     * @return {@link DoubleBuffer}
     */
    private static DoubleBuffer getRandomDoubleBuffer() {
        return doubleBufferMap.get(NumberUtil.getRandomInValue(size));
    }


    private static void task(DoubleBuffer doubleBuffer) throws InterruptedException {
        doubleBuffer.put(1);
        Thread.sleep(1);
    }

    private static void flush(DoubleBuffer doubleBuffer) throws InterruptedException {
        doubleBuffer.flip();
        Thread.sleep(100);
    }

    private static DoubleBufferBeanMap getRandomDoubleBufferMap() {
        return doubleBuffer2Map.get(NumberUtil.getRandomInValue(size));
    }

    private static boolean isNotFull(DoubleBuffer doubleBuffer) {
        return doubleBuffer.hasRemaining();
    }


    static class DoubleBufferBeanMap {
        Map<Boolean, DoubleBuffer> doubleBufferBeans = new HashMap<>();

        DoubleBufferBeanMap() {
            doubleBufferBeans.put(true, DoubleBuffer.allocate(doubleSize));
            doubleBufferBeans.put(false, DoubleBuffer.allocate(doubleSize));
        }

        void slide() {
            System.out.println("切换" + doubleBufferBeans.get(true).position());
            DoubleBuffer trueDoubleBuffer = doubleBufferBeans.get(true);
            DoubleBuffer falseDoubleBuffer = doubleBufferBeans.get(false);
            doubleBufferBeans.put(false, trueDoubleBuffer);
            doubleBufferBeans.put(true, falseDoubleBuffer);
        }

        DoubleBuffer get() {
            return doubleBufferBeans.get(true);
        }

        void flush(DoubleBuffer doubleBuffer) throws InterruptedException {
            if (doubleBuffer.capacity() == doubleBuffer.position()) {
                System.out.println("处理缓存内容" + doubleBuffer.position());
                doubleBuffer.clear();
                Thread.sleep(100);
            }
        }
    }
}

猜你喜欢

转载自blog.csdn.net/just3019/article/details/86682355
今日推荐