常見執行緒不安全的類有哪些呢
下圖中,我們只畫出了最常見的幾種情況,我們常見的collections集合都是執行緒不安全的
我測試的時候輸出為,4985(因為執行緒不安全,所以每次的輸出可能是不同的),如果stringbuilder類為執行緒安全的話,輸出應該為5000
@slf4j
public class stringexample2
public static void main(string args)throws exception catch (exception e)
countdownlatch.countdown();
});}
countdownlatch.await();
executorservice.shutdown();
log.info("size:{}",stringbuffer.length());}}
輸出為5000,且多次測試結果均為5000,證明stringbuffer類是執行緒安全的,通過看stringbuffer的實現可發現,其所有的實現都是加了synchronized關鍵字的,雖然可以保證執行緒安全但是效能是有損耗的,這也證明了stringbuilder的存在價值,如果定義stringbuilder為區域性變數時是沒有執行緒安全問題的,這就用到了上篇部落格我們講的堆疊封閉原理
@slf4j
public class dateformatexample1 catch (parseexception e)
}public static void main(string args)throws exception catch (exception e)
countdownlatch.countdown();
});}
countdownlatch.await();
executorservice.shutdown();}}
執行結果如下:
因為******dateformat為執行緒不安全的類,所以在多執行緒訪問的時候出現了異常
@slf4j
public class dateformatexample2 catch (parseexception e)
}public static void main(string args)throws exception catch (exception e)
countdownlatch.countdown();
});}
countdownlatch.await();
executorservice.shutdown();}}
此demo為demo1的改進版,將******dateformat宣告為區域性變數,運用了堆疊封閉的方式保證了執行緒安全,執行此demo是沒有異常丟擲的
import org.joda.time.datetime;
import org.joda.time.format.datetimeformat;
import org.joda.time.format.datetimeformatter;
@slf4j
public class dateformatexample3 ,{}",i,datetime.parse("20180208", datetimeformatter).todate());
}public static void main(string args)throws exception catch (exception e)
countdownlatch.countdown();
});}
countdownlatch.await();
executorservice.shutdown();}}
joda-time
joda-time
2.9
以下我們做arraylist,hashmap,hashset的例項演示,它們都是執行緒不安全的,還好我們一般都將它們定義為區域性變數(堆疊封閉),如果我們將它們定義為成員變數或static修飾的變數,在多個執行緒同時訪問的時候就很容易出問題。
@slf4j
public class arraylistexample
public static void main(string args)throws exception catch (exception e)
countdownlatch.countdown();
});}
countdownlatch.await();
executorservice.shutdown();
log.info("size:{}", list.size());}}
如果是執行緒安全的輸出應該為5000,實際輸出為4945,且每次執行輸出的值可能不一樣,所以它是執行緒不安全的
@slf4j
public class hashsetexample
public static void main(string args)throws exception catch (exception e)
countdownlatch.countdown();
});}
countdownlatch.await();
executorservice.shutdown();
log.info("size:{}", set.size());}}
輸出為4985,是執行緒不安全的(執行緒安全的話輸出為5000)
@slf4j
public class hashmapexample
public static void main(string args)throws exception catch (exception e)
countdownlatch.countdown();
});}
countdownlatch.await();
executorservice.shutdown();
log.info("size:{}", map.size());}}
輸出為4886(且每次執行輸出值可能不同),是執行緒不安全的(執行緒安全的話輸出為5000)
典型的執行緒不安全的寫法是:先檢查,再執行
if(condition(a)) 就算a是乙個執行緒安全的類所對應的物件,對a的處理handle(a)也是原子性的,但由於這兩步之間的不是原子性的也會引發執行緒安全問題,如a、b兩個執行緒都通過了a的判斷條件,a執行緒執行handle(a)之後,a已經不符合condition(a)的判斷條件了,可是此時b執行緒仍然要執行handle(a),這就引發了執行緒安全問題。
Java併發之執行緒池學習筆記
juc包下有乙個重要的執行緒池的實現,大大優化方便了我們對執行緒的使用,而不再是傳統的new乙個thread。執行緒池相對傳統的直接建立執行緒主要有三個優點 1.統一管理執行緒,可以重用存在的執行緒,避免多次的建立 消亡的開銷,使得效能表現得更好 2.可以有效控制最大併發執行緒數,提高系統資源利用率...
(三)Java併發學習筆記 執行緒封閉
實現好的併發是一件困難的事情,所以很多時候我們都想躲避併發。避免併發最簡單的方法就是執行緒封閉。什麼是執行緒封閉呢?就是把物件封裝到乙個執行緒裡,只有這乙個執行緒能看到此物件。那麼這個物件就算不是執行緒安全的也不會出現任何安全問題。實現執行緒封閉有哪些方法呢?這是完全靠實現者控制的執行緒封閉,他的執...
Java併發學習筆記(6)執行緒的四種狀態,優先順序
執行緒的四種狀態 1.新狀態 執行緒已被建立但尚未執行 start 尚未被呼叫 2.可執行狀態 執行緒可以執行,雖然不一定正在執行。cpu 時間隨時可能被分配給該執行緒,從而使得它執行。4.阻塞狀態 執行緒不會被分配 cpu 時間,無法執行。執行緒的優先順序 執行緒優先順序可以給cpu提供一種建議,...