Java - 【强制】SimpleDateFormat 是线程不安全的类

5. 【强制】SimpleDateFormat 是线程不安全的类,一般不要定义为static变量,如果定义为static,必须加锁,或者使用DateUtils工具类。 正例:注意线程安全,使用DateUtils。亦推荐如下处理:
private static final ThreadLocal<DateFormat> df = new ThreadLocal<DateFormat>() {
@Override
protected DateFormat initialValue() {
return new SimpleDateFormat("yyyy-MM-dd");
}
};
说明:如果是JDK8的应用,可以使用Instant代替Date,LocalDateTime代替Calendar,DateTimeFormatter代替SimpleDateFormat,官方给出的解释:simple beautiful strong immutable thread-safe。

                                                                                                          ——引用《阿里巴巴Java开发手册》

 

/**
	 * private static final SimpleDateFormat dateFormat = new SimpleDateFormat("yyyyMMddHHmmssSSS");
	 * 不推荐使用该方式格式化时间
	 * 【强制】SimpleDateFormat 是线程不安全的类,一般不要定义为static变量,如果定义为static,必须加锁,或者使用DateUtils工具类。 
	 * 正例:注意线程安全,使用DateUtils。亦推荐如下处理:
	 * private static final ThreadLocal<DateFormat> df = new ThreadLocal<DateFormat>() {
	 * @Override
	 * protected DateFormat initialValue() {
	 * return new SimpleDateFormat("yyyy-MM-dd");}};
	 * 说明:如果是JDK8的应用,可以使用Instant代替Date,LocalDateTime代替Calendar,DateTimeFormatter代替SimpleDateFormat,
	 * 官方给出的解释:simple beautiful strong immutable thread-safe。
	 */
	
	
	 /** ☆线程安全,推荐使用☆ */
	private static ThreadLocal<DateFormat> threadLocal = new ThreadLocal<DateFormat>() {
		@Override
		protected DateFormat initialValue() {
			return new SimpleDateFormat("yyyy-MM-dd HH:mm:ss,SSS");
		}
	};
	public static Date formatp(Date date) throws ParseException {
		return threadLocal.get().parse(threadLocal.get().format(date));
	}
	
	/*public static String format(Date date) {
		return threadLocal.get().format(date);
	}
	public static Date formatp(String str) throws ParseException {
		return threadLocal.get().parse(str);
	}*/
		
	private static final SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS");

	public static void main(String[] args) throws ParseException {
		new Thread(){
			@Override
				public void run() {
				while (true){
					String s = null;
					try {
						//s = String.valueOf(simpleDateFormat.parse(simpleDateFormat.format(new Date())).getTime());
						s = String.valueOf(formatp(new Date()).getTime());
					} catch (ParseException e) {
						e.printStackTrace();
					}
					System.out.println("Thread0:\t"+s);
					try {
						Thread.sleep(1000);
					} catch (InterruptedException e) {
						e.printStackTrace();
					}
				}
			}
		}.start();
		new Thread(){
			@Override
				public void run() {
				while (true){
					String s = null;
					try {
						//s = String.valueOf(simpleDateFormat.parse(simpleDateFormat.format(new Date())).getTime());
						s = String.valueOf(formatp(new Date()).getTime());
					} catch (ParseException e) {
						e.printStackTrace();
					}
					System.out.println("Thread1:\t"+s);
					try {
						Thread.sleep(1000);
					} catch (InterruptedException e) {
						e.printStackTrace();
					}
				}
			}
		}.start();
		new Thread(){
			@Override
				public void run() {
				while (true){
					String s = null;
					try {
						//s = String.valueOf(simpleDateFormat.parse(simpleDateFormat.format(new Date())).getTime());
						s = String.valueOf(formatp(new Date()).getTime());
					} catch (ParseException e) {
						e.printStackTrace();
					}
					System.out.println("Thread2:\t"+s);
					try {
						Thread.sleep(1000);
					} catch (InterruptedException e) {
						e.printStackTrace();
					}
				}
			}
		}.start();
}

有兴趣的朋友可以按照上面的代码运行一遍,看一看这两种格式化时间戳的区别:

s = String.valueOf(simpleDateFormat.parse(simpleDateFormat.format(new Date())).getTime());
s = String.valueOf(formatp(new Date()).getTime());

 

posted @ 2022-01-27 18:36  zhangdaopin  阅读(99)  评论(0编辑  收藏  举报