線程安全無處不在

這篇分享作爲一個筆記,原因是今天有人問了我這麼一個問題

public class Test {
	
	private static final SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");

    public static void main(String[] args) throws InterruptedException {
    	
    	Runnable runnable = new Runnable() {
			
			@Override
			public void run() {
				for (int i = 0; i < 100; i++) {
					try {
						sdf.parse("2017-07-28 00:00:00");
					} catch (ParseException e) {
						e.printStackTrace();
					}
				}
				
			}
		};
    	for (int i = 0; i < 100; i++) {
			Thread thread = new Thread(runnable,"t"+i);
			thread.start();
		}
    }
	
}

他問我運行這段代碼會有什麼效果,於是我想起了大概兩年前有個面試官問過我這麼一個問題,SimpleDateFormart用過麼,必然用過啊,對方又問SimpleDateFormat是線程安全的麼,我去,這麼小的一個工具類,有必要問這個麼,這就是我當時的想法,當時我也沒看過源碼,隨便說了個線程不安全,對方又問那如何變得線程安全,我就過腦子都沒過的來了句加鎖,後來馬上補了句加鎖效率肯定會低很多,有可能還會造成線程阻塞,對方說那有沒有別的可以實現線程安全的方法,我便回答每次用都都創建一個新的對象,不管這題打得怎麼樣,反正那次面試是沒有通過。。

迴歸正題,這個代碼一看就是跑多個線程,每個線程一直調用parse方法進行日期轉換,雖然以我現在的水平說不出具體問題所在,不過大概可以知道這應該是一個跟線程安全有關的問題,隨即看了下源碼,SimpleDateFormat確實不是線程安全的,那麼想要避免這個錯誤,可以加鎖但是效率太低沒必要,另一種方式就是每次用的時候創建新的format對象

我們看下面代碼

public class Test {
	

    public static void main(String[] args) throws InterruptedException {
    	
    	Runnable runnable = new Runnable() {
			@Override
			public void run() {
				for (int i = 0; i < 100; i++) {
					try {
						SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
						//便於查看結果,打印日期轉換
						System.out.println(sdf.parse("2017-07-28 00:00:00"));
					} catch (ParseException e) {
						e.printStackTrace();
					}
				}
				
			}
		};
    	for (int i = 0; i < 100; i++) {
			Thread thread = new Thread(runnable,"t"+i);
			thread.start();
		}
    }
	
}
比較low,我直接在每次需要用format的時候構造一個新的對象

本次分享其實沒有什麼實質的意義,也沒有什麼可學習的知識點,只是想告誡下自己線程安全無處不在,多線程是個好東西,但是也是把雙刃劍,使用不慎確實會造成不可預估的風險



發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章