Java实现简单的异步分批记录日志

项目中日志记录是一个不可或缺的部分,通过自己定义日志信息可以保存方便我们排查问题的日志记录。然而传统的同步日志记录方式可能会在高并发环境下成为性能瓶颈。为了解决这个问题,异步日志记录成为了一种流行的优化手段。

编写一个异步日志管理器

import cn.hutool.log.Log;
import cn.hutool.log.LogFactory;

import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

public class AsyncLogger {
    private static final Log log = LogFactory.get();
    private static int BATCH_COMMIT_NUMBER = 200;
    private static final BlockingQueue<String> QUEUE = new LinkedBlockingQueue<>(10000);
    private static final List<String> UNTREATED_LIST = new ArrayList();
    private static final Lock LOCK = new ReentrantLock();
    private static final Condition CONDITION = LOCK.newCondition();

    private AsyncLogger() {
    }

    static {
        Thread loggerThread = new Thread(() -> {
            while (!Thread.currentThread().isInterrupted()) {
                try {
                    LOCK.lock();
                    if (QUEUE.isEmpty()) {
                        CONDITION.await();
                    }
                    while (!QUEUE.isEmpty() && UNTREATED_LIST.size() < BATCH_COMMIT_NUMBER) {
                        UNTREATED_LIST.add(QUEUE.take());
                    }
                    if (!UNTREATED_LIST.isEmpty()) {
                        log.info("达到批次数准备入库!");
                        //TODO 批量入库
                        for (String str : UNTREATED_LIST) {
                            log.info(str);
                        }
                        UNTREATED_LIST.clear();
                    }
                } catch (InterruptedException e) {
                    Thread.currentThread().interrupt();
                    log.error("日志消费发生异常:", e);
                } finally {
                    LOCK.unlock();
                }
            }
        });
        loggerThread.setDaemon(true);
        loggerThread.start();
    }

    public static void putLog(String message) {
        try {
            LOCK.lock();
            QUEUE.put(message);
            CONDITION.signalAll();
        } catch (InterruptedException e) {
            Thread.currentThread().interrupt();
            log.error("添加日志内容发生异常:", e);
        } finally {
            LOCK.unlock();
        }
    }
}

测试一下

    @GetMapping(value = "/find")
    public void find() {
        String orgMsg = "日志内容:";
        for (int i = 1; i <= 100 ; i++) {
            String msg = orgMsg + i;
            AsyncLogger.putLog(msg);
        }
    }

结果展示

  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值