利用java concurrent 包實現日志寫數據庫的並發處理


一、概述

在很多系統中,往往需要將各種操作寫入數據庫(比如客戶端發起的操作)。

最簡單的做法是,封裝一個公共的寫日志的api,各個操作中調用該api完成自己操作日志的入庫。但因為入數據庫效率比較低,如果每個操作自己入庫,則會影響響應速度。而且當操作並發度很高時,往往同時有多個線程在寫數據庫,也會對系統有影響。

考慮的解決方案是,這個api並不實際完成入庫,而是將每個操作日志信息寫到一個公共的緩存中,然后應用系統起了一個獨立的線程(一直運行)在后台進行入庫。如果當前緩存中有記錄,就寫庫,沒有記錄,就堵塞住。

這里關鍵的是要有一個緩存日志的數據結構,我們這里使用java current包中的並發數據結構LinkedBlockingDeque類。

 

二、具體代碼

import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.LinkedBlockingDeque;

public class LogManager implements Runnable {
    //定義緩存數據結構,支持並發操作
    private static LinkedBlockingDeque<ActionLog> list = new LinkedBlockingDeque<ActionLog>();
    static{
        //創建並啟動線程,該線程實現日志的入庫
        new Thread(new LogManager()).start();
    }
    public static void addActionLog(ActionLog log) {
        list.add(log);
    }

    @Override
    public void run() {
        List<ActionLog> items = new ArrayList<ActionLog>();
        while (true) {
            //從緩存中取出1條日志,但不從緩存中刪除。用於檢查隊列中是否有數據
            ActionLog item = list.peek();
            if (item == null && items.size() > 0) {
                //item為null說明緩存中沒有日志了,這時如果臨時隊列items中有記錄,就可以批量入庫了
                work(items);
            }
            //從緩存中取出並刪除最前面的日志,如果無數據,在堵塞
            ActionLog result = deleteItem();
            //將取出的記錄放到臨時隊列中
            items.add(result);
        }
    }

    private ActionLog deleteItem() {
        ActionLog result = null;
        try {
            //取出並刪除最前面的一條數據,如果緩存中無數據,則堵塞住
            result = list.takeFirst();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        return result;
    }

    private void work(List<ActionLog> items) {
        //TODO 完成入庫。這里代碼沒有提供
        //入庫后刪除臨時隊列中記錄
        items.clear();
    }

}

各種工作線程調用 addActionLog 方法將要入庫的日志放到緩存中。由LogManager通過自己的線程控制入庫。

三、小結

上述代碼雖然簡單,但很好的解決了前面提出的問題。不過這個解決方案存在一個問題。

如果說系統產生日志的速度超過了單個線程入庫的速度,上述代碼就有問題。就會造成該線程不停地入庫。

這時就需要考慮增加額外的處理速度,如增加入庫線程。

所以上述代碼,只適合並發日志量不是特別大的情況下的場景。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM