Browse Source

底层日志组件SimpleDateFormat线程安全问题修复;

xuxueli 7 years ago
parent
commit
c1ca3fbe53

+ 12 - 12
doc/XXL-JOB官方文档.md

@@ -1239,7 +1239,8 @@ Tips: 历史版本(V1.3.x)目前已经Release至稳定版本, 进入维护阶段
 - 23、执行器手动设置IP时取消绑定Host的操作,该IP仅供执行器注册使用;修复指定外网IP时无法绑定执行器Host的问题;
 - 24、取消父子任务不可重复的限制,支持循环任务触发等特殊场景;
 - 25、任务调度备注中标注任务触发类型,如Cron触发、父任务触发、API触发等等,方便排查调度日志;
-- 26、【迭代中】分片任务失败重试优化,仅重试当前失败的分片;
+- 26、底层日志组件SimpleDateFormat线程安全问题修复;
+- 27、【迭代中】分片任务失败重试优化,仅重试当前失败的分片;
 
 
 ### TODO LIST
@@ -1255,17 +1256,16 @@ Tips: 历史版本(V1.3.x)目前已经Release至稳定版本, 进入维护阶段
 - 10、Bean模式任务,JobHandler自动从执行器中查询展示为下拉框,选择后自动填充任务名称等属性;
 - 11、API事件触发类型任务(更类似MQ消息)支持"动态传参、延时消费";该类型任务不走Quartz,单独建立MQ消息表,调度中心竞争触发;待定,该功能与 XXL-MQ 冲突,该场景建议用后者;
 - 12、任务依赖增强,新增任务类型 "流程任务",流程节点可挂载普通类型任务,承担任务依赖功能。现有子任务模型取消;需要考虑任务依赖死循环问题;
-- 13、分片任务某一分片失败,支持分片转移;
-- 14、调度中心触发任务后,先推送触发队列,异步触发,然后立即返回。降低quartz线程占用时长。
-- 15、任务告警逻辑调整:任务调度,以及任务回调失败时,均推送监控队列。后期考虑通过任务Log字段控制告警状态;
-- 16、新增任务默认运行状态,任务更新时运行状态保持不变;
-- 17、提供多版本执行器:不依赖容器版本、不内嵌Jetty版本(通过配置executoraddress替换jetty通讯)等;
-- 18、注册中心支持扩展,除默认基于DB之外,支持扩展接入第三方注册中心如zk、eureka等;
-- 19、流程任务,支持参数传递;
-- 20、SimpleTrigger 支持;
-- 21、支持通过API服务操作任务信息;
-- 22、调度线程池改为协程方式实现,大幅降低系统内存消耗;
-- 23、API任务触发时支持动态传参;
+- 13、调度中心触发任务后,先推送触发队列,异步触发,然后立即返回。降低quartz线程占用时长。
+- 14、任务告警逻辑调整:任务调度,以及任务回调失败时,均推送监控队列。后期考虑通过任务Log字段控制告警状态;
+- 15、新增任务默认运行状态,任务更新时运行状态保持不变;
+- 16、提供多版本执行器:不依赖容器版本、不内嵌Jetty版本(通过配置executoraddress替换jetty通讯)等;
+- 17、注册中心支持扩展,除默认基于DB之外,支持扩展接入第三方注册中心如zk、eureka等;
+- 18、流程任务,支持参数传递;
+- 19、SimpleTrigger 支持;
+- 20、支持通过API服务操作任务信息;
+- 21、调度线程池改为协程方式实现,大幅降低系统内存消耗;
+- 22、API任务触发时支持动态传参;
 
 ## 七、其他
 

+ 2 - 3
xxl-job-core/src/main/java/com/xxl/job/core/log/XxlJobLogger.java

@@ -1,5 +1,6 @@
 package com.xxl.job.core.log;
 
+import com.xxl.job.core.util.DateUtil;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 import org.slf4j.helpers.FormattingTuple;
@@ -7,7 +8,6 @@ import org.slf4j.helpers.MessageFormatter;
 
 import java.io.PrintWriter;
 import java.io.StringWriter;
-import java.text.SimpleDateFormat;
 import java.util.Date;
 
 /**
@@ -15,7 +15,6 @@ import java.util.Date;
  */
 public class XxlJobLogger {
     private static Logger logger = LoggerFactory.getLogger("xxl-job logger");
-    private static SimpleDateFormat xxlJobLoggerFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");   // TODO,concurrent issue
 
     /**
      * append log
@@ -31,7 +30,7 @@ public class XxlJobLogger {
         StackTraceElement callInfo = stackTraceElements[1];*/
 
         StringBuffer stringBuffer = new StringBuffer();
-        stringBuffer.append(xxlJobLoggerFormat.format(new Date())).append(" ")
+        stringBuffer.append(DateUtil.format(new Date())).append(" ")
             .append("["+ callInfo.getClassName() + "#" + callInfo.getMethodName() +"]").append("-")
             .append("["+ callInfo.getLineNumber() +"]").append("-")
             .append("["+ Thread.currentThread().getName() +"]").append(" ")

+ 30 - 0
xxl-job-core/src/main/java/com/xxl/job/core/util/DateUtil.java

@@ -0,0 +1,30 @@
+package com.xxl.job.core.util;
+
+import java.text.ParseException;
+import java.text.SimpleDateFormat;
+import java.util.Date;
+
+/**
+ * date util
+ *
+ * @author xuxueli 2018-08-19 01:24:11
+ */
+public class DateUtil {
+    private static final String DATE_FORMAT = "yyyy-MM-dd HH:mm:ss";
+
+    private static ThreadLocal<SimpleDateFormat> threadLocal = new ThreadLocal<SimpleDateFormat>() {
+        @Override
+        protected synchronized SimpleDateFormat initialValue() {
+            //return super.initialValue();
+            return new SimpleDateFormat(DATE_FORMAT);
+        }
+    };
+
+    public static String format(Date date) {
+        return threadLocal.get().format(date);
+    }
+
+    public static Date parse(String textDate) throws ParseException {
+        return threadLocal.get().parse(textDate);
+    }
+}