有没有一种正确的方法来使用默认的Java库为控制台输出添加时间戳?

时间:2017-05-30 15:43:12

标签: java performance logging

当我处理个人Java项目时,我喜欢将文本很好地记录到控制台。我通常为此创建一些公共静态类来处理前缀并将时间戳应用于消息,因此我可以省略System.out.println(“Text”)的用法;

这是我前一段时间写的课程,我倾向于在不同的项目中重复使用它,因为我非常喜欢它格式化文本的方式:

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

public class Log {

    public static final int LEVEL_INFO = 0;
    public static final int LEVEL_WARNING = 1;
    public static final int LEVEL_ERROR = 2;

    private static SimpleDateFormat df = new SimpleDateFormat("HH:mm:ss");
    /**
     * Used instead of System.out.println for consistent formatting.
     *
     * @param messageToPrefix Message that you want to send to print.
     * @param errorLevel Type of message you want to send.
     */
    public static void print(String messageToPrefix, int errorLevel) {
        StringBuilder message = new StringBuilder();
        message.append("[").append(df.format(new Date())).append("] ");
        switch(errorLevel) {
            case LEVEL_INFO:
                 message.append("[Info] ");
                break;
            case LEVEL_WARNING:
                message.append("[Warning] ");
                break;
            case LEVEL_ERROR:
                message.append("[Error] ");
                break;
        }
        message.append(messageToPrefix);
        System.out.println(message.toString());
    }
}

这一切都按预期工作,但我刚才注意到一个小问题:这种创建时间戳的方式非常耗费资源!调用此方法需要我想要记录的代码暂停,直到时间戳已经生成并写入控制台。这对我来说似乎效率低下(即使我们在这里谈论几毫秒)。当我将这个日志记录方法的运行时与使用System.currentTimeMillis()的运行时进行比较时,我得出了这个结论,而System.currentTimeMillis()没有将它格式化为一个漂亮的时间戳,但是如果像这样使用,则显示运行时的ms:

public class Log {

    private static final long startTime = System.currentTimeMillis();

    public static final int LOG_LEVEL_INFO = 0;
    public static final int LOG_LEVEL_WARNING = 1;
    public static final int LOG_LEVEL_ERROR = 2;
    public static final int LOG_LEVEL_UNKNOWN = 3;

    /**
     * Used instead of System.out.println for consistent formatting.
     *
     * @param msg Message that you want to send to log.
     * @param importance How important is the message?
     */
    public static void print(String msg, int importance) {
        StringBuilder finalMsg = new StringBuilder();
        finalMsg.append("[").append(System.currentTimeMillis() - startTime).append(" ms] ");
        switch (importance) {
            case 0:
                finalMsg.append("[INFO] ");
                break;
            case 1:
                finalMsg.append("[WARNING] ");
                break;
            case 2:
                finalMsg.append("[ERROR] ");
                break;
            default:
                finalMsg.append("[UNKNOWN] ");
                break;
        }
        finalMsg.append(msg);
        System.out.println(finalMsg);
    }
}

这种方式被证明是更快的,即使是大约50个消息的小规模。 50秒的运行时间。

这让我想到了几个问题: 有没有更好的方法来创建这样的时间戳? 有没有办法不等待日志代码完成? 为这个开始一个线程是个好主意吗? 或者我完全走错了轨道?

我不想使用任何额外的库来保持它小而简单。

任何建议都将不胜感激!

1 个答案:

答案 0 :(得分:0)

编辑:好吧我认为(在遵循一些建议之后)这是一种安全的记录和时间戳消息的方法。它可能不是最快的方法,但它可以安全使用并给我我想要的结果。

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

    public class Log {

        public static final int LEVEL_INFO = 0;
        public static final int LEVEL_WARNING = 1;
        public static final int LEVEL_ERROR = 2;

        private static final ThreadLocal<SimpleDateFormat> formatter = ThreadLocal.withInitial(() -> new SimpleDateFormat("HH:mm:ss"));

        /**
         * Used instead of System.out.println for consistent formatting.
         *
         * @param messageToPrefix Message that you want to send to print.
         * @param errorLevel Type of message you want to send.
         */
        public static void print(String messageToPrefix, int errorLevel) {
            StringBuilder message = new StringBuilder();
            message.append("[").append(formatter.get().format(new Date())).append("] ");
            switch(errorLevel) {
                case LEVEL_INFO:
                    message.append("[Info] ");
                    break;
                case LEVEL_WARNING:
                    message.append("[Warning] ");
                    break;
                case LEVEL_ERROR:
                    message.append("[Error] ");
                    break;
            }
            message.append(messageToPrefix);
            System.out.println(message.toString());
        }
    }

我要感谢评论中的人们提供的所有建议。