java多线程日志文件隔离

前言

实际项目开发过程中,为了加快程序计算处理速度,我们常常会用到多线程技术,但是由于多个线程都是异步执行,所以每个线程打印的日志会相互干扰、散乱混杂,变得难以阅读和追踪,这篇文件我们就来解决一下这个问题。

我想到的解放办法有两种,一种是给线程命名,打印日志时加入线程名称,查找时候再通过线程名来进行筛选过滤。这种方式的优点是比较简单直接,代码改动量小,而且能够一次将所有有报错日志的线程都查找出来,缺点是日志文件很大时查找会比较慢。

第二种方法是给每个线程新建一个单独的日志文件,这样查看哪个线程日志就去找对应文件。优点是文件相互隔离,内容清晰,缺点是不能统一查找报错日志了。具体需要使用哪种方案还是需要根据使用场景和实际需求来选择。

本文主要介绍第二种方法的实现。

log4j

我们以常用的日志实现类log4j为例,maven坐标如下

<dependency>
    <groupId>log4j</groupId>
    <artifactId>log4j</artifactId>
    <version>1.2.17</version>
</dependency>

 创建线程日志类

import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.Date;

import org.apache.log4j.DailyRollingFileAppender;
import org.apache.log4j.Level;
import org.apache.log4j.Logger;
import org.apache.log4j.PatternLayout;

public class ThreadLogger {

    public static Logger getLogger(String logName) {

        PatternLayout layout = new PatternLayout("[%d{MM-dd HH:mm:ss}] %-5p %-8t %m%n");

        // 日志文件按照每天分文件夹存放
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
        String logPath = "/log/" + sdf.format(new Date()) + "/" + logName + ".log";

        // 文件输出
        DailyRollingFileAppender fileAppender = null;

        try {
            fileAppender = new DailyRollingFileAppender(layout, logPath, "yyyy-MM-dd");
            fileAppender.setAppend(false);
            fileAppender.setImmediateFlush(true);
            fileAppender.setThreshold(Level.DEBUG);
            fileAppender.activateOptions();
        } catch (IOException e) {
            e.printStackTrace();
        }

        // 绑定到logger
        Logger logger = Logger.getLogger(logName);
        logger.setLevel(Level.DEBUG);
        logger.addAppender(fileAppender);

        return logger;
    }
}

自定义线程类进行测试

import org.apache.log4j.Logger;

public class MyThread implements Runnable {
    Logger logger;

    public MyThread(String logName) {
        logger = ThreadLogger.getLogger(logName);
    }

    public void run() {
        logger.debug("debug start");
        logger.info("thread started!");
        logger.error("error");
        logger.info("thread finished!");
    }

    public static void main(String[] args) {
        for (int i = 0; i < 20; i++) {
            MyThread myThread = new MyThread(i+"");
            myThread.run();
        }
    }
}

结果

总结

给线程设置单独日志的核心就是要让每个线程持有自己的log对象,并且在log对象中通过appender设置线程自己日志格式和路径。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值