先上两个BUG
BUG 1:
| 12
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 
 | package ThreadLocal;
 import java.text.ParseException;
 import java.text.SimpleDateFormat;
 import java.util.Date;
 
 
 
 
 
 
 
 public class SimpleDateFormatBugTest {
 
 private static SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
 
 private static Date parse(String date){
 try {
 return sdf.parse(date);
 }catch (ParseException e){
 e.printStackTrace();
 }
 return null;
 }
 
 public static void main(String[] args) {
 Thread thread1 = new Thread(() -> {
 Date parse = parse("2020-04-24 15:54:59");
 System.out.println("第一次执行时间:" + parse);
 });
 
 Thread thread2 = new Thread(() -> {
 Date parse = parse("2020-04-25 15:54:59");
 System.out.println("第二次执行时间:" + parse);
 });
 
 Thread thread3 = new Thread(() -> {
 Date parse = parse("2020-04-26 15:54:59");
 System.out.println("第三次执行时间:" + parse);
 });
 
 thread1.start();
 thread2.start();
 thread3.start();
 
 try {
 thread1.join();
 thread2.join();
 thread3.join();
 } catch (InterruptedException e) {
 e.printStackTrace();
 }
 System.out.println("线程退出");
 }
 
 }
 
 | 

多线程下使用同一个SimpleDateFormat实例将String日期格式转换成Date只能获取到其中一次的结果,其他两个线程出错
BUG 2:
| 12
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 
 | package ThreadLocal;
 import java.text.ParseException;
 import java.util.Date;
 
 
 
 
 
 
 
 public class SimpleDateFormat {
 
 private static java.text.SimpleDateFormat sdf = new java.text.SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
 private static Date d1 = null;
 private static Date d2 = null;
 private static Date d3 = null;
 
 static {
 try {
 d1 = sdf.parse("2020-04-24 15:54:59");
 d2 = sdf.parse("2020-04-25 15:54:59");
 d3 = sdf.parse("2020-04-26 15:54:59");
 } catch (ParseException e) {
 e.printStackTrace();
 }
 }
 public static void main(String[] args) {
 Thread thread1 = new Thread(() -> {
 String format = sdf.format(d1);
 System.out.println("第一次执行时间:" + format);
 });
 
 Thread thread2 = new Thread(() -> {
 String format = sdf.format(d2);
 System.out.println("第二次执行时间:" + format);
 });
 
 Thread thread3 = new Thread(() -> {
 String format = sdf.format(d3);
 System.out.println("第三次执行时间:" + format);
 });
 
 thread1.start();
 thread2.start();
 thread3.start();
 
 System.out.println("线程退出");
 }
 }
 
 | 

同样在多线程下如果将Date转成String的话,多个线程共享了同一个数据,导致获取的时间为同一个数据
如何解决
解决方案一:ThreadLocal


原因分析:
SimpleDateFormat是线程不安全的,具体可以从parse(source, pos)方法中得到答案
| 1
 | parsedDate = calb.establish(calendar).getTime();
 | 
calendar是成员变量,成员变量在多线程下如果没有锁的限制的话,就很容易出现线程安全问题。
那使用synchronized也可以做到线程安全,但是锁会降低线程的执行效率
解决方案二:synchronized
