非線程安全的類-SimpleDateFormat

類SimpleDateFormat主要負責日期的轉換與格式化,但在多線程的環境中,使用此類容易形成數據轉換及處理的不正確,由於SimpleDateFormat並非線程安全的,咱們看一段代碼:java

package chapter7.testsimpledateformat;

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

public class MyThread extends Thread{
	
	private SimpleDateFormat sdf;
	private String dateString;
	
	public MyThread(SimpleDateFormat sdf,String dateString) {
		this.sdf = sdf;
		this.dateString = dateString;
	}
	
	@Override
	public void run() {
		try {
			super.run();
			Date dateRef = sdf.parse(dateString);
			String newDateStr = sdf.format(dateRef).toString();
			if(!newDateStr.equals(dateString)) {
				System.out.println("ThreadName="+this.getName()+"報錯了 日期字符串:"+dateString+" 轉換成的日期爲:"+newDateStr);
			}
		} catch (Exception e) {
			e.printStackTrace();
		}
	}

}

 

package chapter7.testsimpledateformat;

import java.text.SimpleDateFormat;

public class Test {
	
	public static void main(String[] args) {
		SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
		String[] dateStr = new String[] {"2000-01-01","2000-01-02","2000-01-03","2000-01-04","2000-01-05","2000-01-06","2000-01-07","2000-01-08","2000-01-09","2000-01-10"};
		MyThread[] threads = new MyThread[10];
		for(int i=0;i<10;i++) {
			threads[i] = new MyThread(sdf, dateStr[i]);
		}
		for(int i=0;i<10;i++) {
			threads[i].start();
		}
	}

}

 運行結果:安全

ThreadName=Thread-5報錯了 日期字符串:2000-01-06 轉換成的日期爲:2000-01-02
ThreadName=Thread-6報錯了 日期字符串:2000-01-07 轉換成的日期爲:2000-01-01
ThreadName=Thread-2報錯了 日期字符串:2000-01-03 轉換成的日期爲:2000-01-05
ThreadName=Thread-3報錯了 日期字符串:2000-01-04 轉換成的日期爲:0010-01-10
ThreadName=Thread-4報錯了 日期字符串:2000-01-05 轉換成的日期爲:2000-01-10多線程

解決辦法1:ide

package chapter7.testsimpledateformat;

import java.util.Date;

public class MyThread extends Thread{
	
	private String dateString;
	
	public MyThread(String dateString) {
		this.dateString = dateString;
	}
	
	@Override
	public void run() {
		try {
			super.run();
			Date dateRef = DateTools.parse(dateString);
			String newDateStr = DateTools.format(dateRef);
			if(!newDateStr.equals(dateString)) {
				System.out.println("ThreadName="+this.getName()+"報錯了 日期字符串:"+dateString+" 轉換成的日期爲:"+newDateStr);
			}
		} catch (Exception e) {
			e.printStackTrace();
		}
	}

}

 

package chapter7.testsimpledateformat;

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

public class DateTools {
	
	private static final String DATE_FORMAT = "yyyy-MM-dd";
	
	public static Date parse(String dateStr) throws ParseException {
		return new SimpleDateFormat(DATE_FORMAT).parse(dateStr);
	}
	
	public static String format(Date date){
		return new SimpleDateFormat(DATE_FORMAT).format(date);
	}

}

 

package chapter7.testsimpledateformat;

public class Test {
	
	public static void main(String[] args) {
		try {
			String[] dateStr = new String[] {"2000-01-01","2000-01-02","2000-01-03","2000-01-04","2000-01-05","2000-01-06","2000-01-07","2000-01-08","2000-01-09","2000-01-10"};
			MyThread[] threads = new MyThread[10];
			for(int i=0;i<10;i++) {
				threads[i] = new MyThread(dateStr[i]);
			}
			for(int i=0;i<10;i++) {
				threads[i].start();
			}
		} catch (Exception e) {
			e.printStackTrace();
		}

	}

}

 運行結果:沒有打印錯誤,說明問題解決,解決處理錯誤的原理其實就是建立多個SimpleDateFormat。this

解決方法2:線程

package chapter7.testsimpledateformat;

import java.util.Date;

public class MyThread extends Thread{
	
	private String dateString;
	
	public MyThread(String dateString) {
		this.dateString = dateString;
	}
	
	@Override
	public void run() {
		try {
			super.run();
			Date dateRef = DateTools.getSimpleDateFormat().parse(dateString);
			String newDateStr = DateTools.getSimpleDateFormat().format(dateRef);
			if(!newDateStr.equals(dateString)) {
				System.out.println("ThreadName="+this.getName()+"報錯了 日期字符串:"+dateString+" 轉換成的日期爲:"+newDateStr);
			}
		} catch (Exception e) {
			e.printStackTrace();
		}
	}

}

 

package chapter7.testsimpledateformat;

import java.text.SimpleDateFormat;

public class DateTools {
	
	private static final String DATE_FORMAT = "yyyy-MM-dd";
	private static ThreadLocal<SimpleDateFormat> tlLocal = new ThreadLocal<SimpleDateFormat>();
	
	public static SimpleDateFormat getSimpleDateFormat() {
		SimpleDateFormat sdf = null;
		sdf = tlLocal.get();
		if(sdf == null) {
			sdf = new SimpleDateFormat(DATE_FORMAT);
			tlLocal.set(sdf);
		}
		return sdf;
	}
	
}

 運行結果:沒有輸出錯誤,說明用ThreadLocal能夠解決問題,ThreadLocal類能使線程綁定到指定的對象。orm

相關文章
相關標籤/搜索