(四)Java併發學習筆記 執行緒不安全類與寫法

2021-09-20 04:58:27 字數 3859 閱讀 1091

常見執行緒不安全的類有哪些呢

下圖中,我們只畫出了最常見的幾種情況,我們常見的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提供一種建議,...