手写高并发下的双缓冲(分段锁,事务性,高并发,顺序性)

双缓冲机制是在hadoop刷写元数据的时候进行的操作。

模仿hadoop刷写的过程编写简易的双缓冲代码。

import java.util.LinkedList;
import java.util.concurrent.atomic.LongAdder;


public class FSEditlog {

    public class Editlog {
        private long txid;//事务ID
        private String log;//日志

        public Editlog(long txid, String log) {
            this.txid = txid;
            this.log = log;
        }

        @Override
        public String toString() {
            return "Editlog{" +
                    "txid=" + txid +
                    ", log='" + log + '\'' +
                    '}';
        }
    }

    public class DoubleBuf {
        //第一块内存  bufCurrent
        LinkedList<Editlog> bufCurrent = new LinkedList<Editlog>();
        //第二块内存   bufReady
        LinkedList<Editlog> bufReady = new LinkedList<Editlog>();

        //写入内存操作
        public void write(Editlog editlog) {
            bufCurrent.add(editlog);
        }

        //写磁盘,元数据持久化
        public void flush() {
            for (Editlog editlog : bufReady) {
                System.out.println("当前线程ID: " + Thread.currentThread().getId() + "  当前元数据刷到磁盘:" + editlog);
            }
            //刷完盘之后,清空内存
            bufReady.clear();
        }

        //交换内存
        public void setReadyToFlush() {
            LinkedList<Editlog> temp = bufCurrent;
            bufCurrent = bufReady;
            bufReady = temp;
        }

        //获取最大事务ID
        public long getMaxTxid() {
            return bufReady.getLast().txid;
        }
    }

    //记录事务id
    LongAdder txid = new LongAdder();
    DoubleBuf doubleBuf = new DoubleBuf();
    ThreadLocal<Long> threadLocal = new ThreadLocal<Long>();

    public void writeEditlog(String log) {
        synchronized (this) {
            txid.increment(); // 1 2 3 4
            threadLocal.set(txid.longValue());
            final Editlog editlog = new Editlog(txid.longValue(), log);
            doubleBuf.write(editlog);
        }
        //持久化元数据
        logSync();
    }

    //是否正在同步刷盘的标志位
    public boolean isSyncRunning = false;
    //记录最大事务ID , 以后只操作最大的事务iD
    long syncStart = 0;
    //是否线程等待标志位
    boolean isWait = false;

    //刷盘操作
    public void logSync() {
        //锁开始
        synchronized (this) {
            //有线程正在刷盘
            if (isSyncRunning) {
                //如果当前线程id < 最大事务id,意味着当前线程工作已经被其他线程完成了
                //说明当前线程任务已经被其他线程处理完毕了,所以什么也不用做
                if (threadLocal.get() < syncStart) {
                    return;
                }
                if (isWait) {
                    return;
                }
                isWait = true;
                while (isSyncRunning) {   //线程2 进来了,发现线程1处于isSyncRunning ,  线程2等待
                    try {
                        this.wait(1000);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
                //此时刷盘结束,不需要等待了
                isWait = true;
            }
            //交换内存
            doubleBuf.setReadyToFlush();
            //更新获取最大事务Id
            if (doubleBuf.bufReady.size() > 0) {
                syncStart = doubleBuf.getMaxTxid();
            }
            //交换内存之后,具备了刷盘条件
            isSyncRunning = true;
        }//锁结束
        doubleBuf.flush();
        //刷完
        synchronized (this) {
            isSyncRunning = false;
            this.notifyAll();
        }
    }

    public static void main(String[] args) {

        final FSEditlog fsEditlog = new FSEditlog();
        boolean isRunning = true;
        long txid = 0;
        while (isRunning) {
            txid++;
            if (txid == 100) {
                isRunning = false;
            }
            new Thread(new Runnable() {
                boolean isRunning = true;
                long txid = 0;

                @Override
                public void run() {
                    while (isRunning) {
                        txid++;
                        if (txid == 100) {
                            isRunning = false;
                        }
                        fsEditlog.writeEditlog("元数据");
                    }
                }
            }).start();
        }
    }

}

运行结果如下:

猜你喜欢

转载自blog.csdn.net/weixin_40954192/article/details/107136027
今日推荐