導航:首頁 > 編程語言 > java線程安全set

java線程安全set

發布時間:2023-02-01 02:11:10

java開發中線程的安全問題以及產生的原因

Java如何保證原子性常用的保證Java操作原子性的工具是鎖和同步方法(或者同步代碼塊)。使用鎖,可以保證同一時間只有一個線程能拿到鎖,也就保證了同一時間只有一個線程能執行申請鎖和釋放鎖之間的代碼。
與鎖類似的是同步方法或者同步代碼塊。使用非靜態同步方法時,鎖住的是當前實例;使用靜態同步方法時,鎖住的是該類的Class對象;使用靜態代碼塊時,鎖住的是synchronized關鍵字後面括弧內的對象。

② Java中HashMap,HashSet是線程安全的嗎,ArrayList是線程不安全的那如何避免其出異常

HashMap,HashSet,ArrayList都不具備線程安全。

可以用

Sets=Collections.synchronizedSet(newHashset<...>());
Mapm=Collections.synchronizedMap(newHashMap<...>());
Listl=Collections.synchronizedList(newArrayList<...>());

獲得被同步後的版本。


也可以用ConcurrentHashMap等同步工具代替

③ java線程安全的容器有哪些

1、你是指並發操作時的線程安全嗎?
2、容器中線程安全的如:vectory,hashtable,非線程安全的如:hashmap,arrylist等。
3、對於原定義非線程的容器如:hashmap,arraylist可以使用Collections中的synchronizedList(list),synchronizedMap(map),synchronizedSet(set)等方法來使原來非線程安全的容器編程線程安全。
4、另一方面容器中使用泛型:容器<類型>也是使容器安全的一種方式。

④ Java的List如何實現線程安全

Java的List如何實現線程安全?

Collections.synchronizedList(names);效率最高,線程安全

Java的List是我們平時很常用的集合,線程安全對於高並發的場景也十分的重要,那麼List如何才能實現線程安全呢 ?


加鎖

首先大家會想到用Vector,這里我們就不討論了,首先討論的是加鎖,例如下面的代碼


public class Synchronized{

private List<String> names = new LinkedList<>();

public synchronized void addName(String name ){
names.add("abc");
}
public String getName(Integer index){
Lock lock =new ReentrantLock();
lock.lock();
try {
return names.get(index);
}catch (Exception e){
e.printStackTrace();
}
finally {
lock.unlock();
}
return null;
}
}

synchronized一加,或者使用lock 可以實現線程安全,但是這樣的List要是很多個,代碼量會大大增加。

java自帶類

在java中我找到自帶有兩種方法


CopyOnWriteArrayList

CopyOnWrite 寫入時復制,它使一個List同步的替代品,通常情況下提供了更好的並發性,並且避免了再迭代時候對容器的加鎖和復制。通常更適合用於迭代,在多插入的情況下由於多次的復制性能會一定的下降。


下面是add方法的源代碼


public boolean add(E e) {
final ReentrantLock lock = this.lock; // 加鎖 只允許獲得鎖的線程訪問
lock.lock();
try {
Object[] elements = getArray();
int len = elements.length;
// 創建個長度加1的數組並復制過去
Object[] newElements = Arrays.Of(elements, len + 1);
newElements[len] = e; // 賦值
setArray(newElements); // 設置內部的數組
return true;
} finally {
lock.unlock();
}
}


Collections.synchronizedList

Collections中有許多這個系列的方法例如


主要是利用了裝飾者模式對傳入的集合進行調用 Collotions中有內部類SynchronizedList


static class SynchronizedList<E>
extends SynchronizedCollection<E>
implements List<E> {
private static final long serialVersionUID = -7754090372962971524L;

final List<E> list;

SynchronizedList(List<E> list) {
super(list);
this.list = list;
}
public E get(int index) {
synchronized (mutex) {return list.get(index);}
}
public E set(int index, E element) {
synchronized (mutex) {return list.set(index, element);}
}
public void add(int index, E element) {
synchronized (mutex) {list.add(index, element);}
}
public E remove(int index) {
synchronized (mutex) {return list.remove(index);}
}

static class SynchronizedCollection<E> implements Collection<E>, Serializable {
private static final long serialVersionUID = 3053995032091335093L;

final Collection<E> c; // Backing Collection
final Object mutex; // Object on which to synchronize


這里上面的mutex就是鎖的對象 在構建時候可以指定鎖的對象 主要使用synchronize關鍵字實現線程安全

/**
* @serial include
*/
static class SynchronizedList<E>
extends SynchronizedCollection<E>
implements List<E> {
private static final long serialVersionUID = -7754090372962971524L;

final List<E> list;

SynchronizedList(List<E> list) {
super(list);
this.list = list;
}
SynchronizedList(List<E> list, Object mutex) {
super(list, mutex);
this.list = list;
}
這里只是列舉SynchronizedList ,其他類類似,可以看下源碼了解下。

測試
public class Main {
public static void main(String[] args) {
List<String> names = new LinkedList<>();
names.add("sub");
names.add("jobs");
// 同步方法1 內部使用lock
long a = System.currentTimeMillis();
List<String> strings = new CopyOnWriteArrayList<>(names);
for (int i = 0; i < 100000; i++) {
strings.add("param1");
}
long b = System.currentTimeMillis();
// 同步方法2 裝飾器模式使用 synchronized
List<String> synchronizedList = Collections.synchronizedList(names);
for (int i = 0; i < 100000; i++) {
synchronizedList.add("param2");
}
long c = System.currentTimeMillis();
System.out.println("CopyOnWriteArrayList time == "+(b-a));
System.out.println("Collections.synchronizedList time == "+(c-b));
}
}


兩者內部使用的方法都不一樣,CopyOnWriteArrayList內部是使用lock進行加鎖解鎖完成單線程訪問,synchronizedList使用的是synchronize

進行了100000次添加後時間對比如下:

可以看出來還是使用了synchronize的集合工具類在添加方面更加快一些,其他方法這里篇幅關系就不測試了,大家有興趣去試一下。

⑤ 創建一個線程安全的set集合

可以利用Collections工具類的synchronizedSet方法修飾一個非同步的Set變成同步Set

Set<T>set=newHashSet<T>();//非同步,非線程安全的Set
Set<T>syncSet=Collections.synchronizedSet(set);//返回了一個線程安全的Set

⑥ java是線程安全的嗎

線程安全就是多線程訪問時,採用了加鎖機制,當一個線程訪問該類的某個數據時,進行保護,其他線程不能進行訪問直到該線程讀取完,其他線程才可使用。不會出現數據不一致或者數據污染。(Vector,HashTab;le)
線程不安全就是不提供數據訪問保護,有可能出現多個線程先後更改數據造成所得到的數據是臟數據。(ArrayList,LinkedList,HashMap等)
概念:
如果你的代碼所在的進程中有多個線程在同時運行,而這些線程可能會同時運行這段代碼。如果每次運行結果和單線程運行的結果是一樣的,而且其他的變數的值也和預期的是一樣的,就是線程安全的。或者說:一個類或者程序所提供的介面對於線程來說是原子操作或者多個線程之間的切換不會導致該介面的執行結果存在二義性,也就是說我們不用考慮同步的問題。線程安全問題都是由全局變數及靜態變數引起的。
若每個線程中對全局變數、靜態變數只有讀操作,而無寫操作,一般來說,這個全局變數是線程安全的;若有多個線程同時執行寫操作,一般都需要考慮線程同步,否則的話就可能影響線程安全。
例子:
比如一個 ArrayList 類,在添加一個元素的時候,它可能會有兩步來完成:1. 在 Items[Size] 的位置存放此元素;2. 增大 Size 的值。
在單線程運行的情況下,如果 Size = 0,添加一個元素後,此元素在位置 0,而且 Size=1;
而如果是在多線程情況下,比如有兩個線程,線程 A 先將元素存放在位置 0。但是此時 CPU 調度線程A暫停,線程 B
得到運行的機會。線程B也向此 ArrayList 添加元素,因為此時 Size 仍然等於 0
(注意哦,我們假設的是添加一個元素是要兩個步驟哦,而線程A僅僅完成了步驟1),所以線程B也將元素存放在位置0。然後線程A和線程B都繼續運行,都增加
Size 的值。
那好,我們來看看 ArrayList 的情況,元素實際上只有一個,存放在位置 0,而 Size 卻等於 2。這就是「線程不安全」了。
安全性:
線程安全性不是一個非真即假的命題。 Vector 的方法都是同步的,因為java會有相應的機制是同一時刻只有一個線程對這個變數操作。並且
Vector 明確地設計為在多線程環境中工作。但是它的線程安全性是有限制的,即在某些方法之間有狀態依賴(類似地,如果在迭代過程中 Vector
被其他線程修改,那麼由 Vector.iterator() 返回的
iterator會拋出)。
對於 Java 類中常見的線程安全性級別,沒有一種分類系統可被廣泛接受,不過重要的是在編寫類時盡量記錄下它們的線程安全行為。
Bloch 給出了描述五類線程安全性的分類方法:不可變、線程安全、有條件線程安全、線程兼容和線程對立。只要明確地記錄下線程安全特性,那麼您是否使用這種系統都沒關系。這種系統有其局限性
– 各類之間的界線不是百分之百地明確,而且有些情況它沒照顧到 –
但是這套系統是一個很好的起點。這種分類系統的核心是調用者是否可以或者必須用外部同步包圍操作(或者一系列操作)。下面幾節分別描述了線程安全性的這五種類別。
不可變
不可變的對象一定是線程安全的,並且永遠也不需要額外的同步。因為一個不可變的對象只要構建正確,其外部可見狀態永遠也不會改變,永遠也不會看到它處於不一致的狀態。Java
類庫中大多數基本數值類如 Integer 、 String 和 BigInteger 都是不可變的。
需要注意的是,對於Integer,該類不提供add方法,加法是使用+來直接操作。而+操作是不具線程安全的。這是提供原子操作類AtomicInteger的原。
線程安全
線程安全的對象具有在上面「線程安全」一節中描述的屬性 –
由類的規格說明所規定的約束在對象被多個線程訪問時仍然有效,不管運行時環境如何排線程都不需要任何額外的同步。這種線程安全性保證是很嚴格的 –
許多類,如 Hashtable 或者 Vector 都不能滿足這種嚴格的定義。
有條件的線程安全
有條件的線程安全類對於單獨的操作可以是線程安全的,但是某些操作序列可能需要外部同步。條件線程安全的最常見的例子是遍歷由 Hashtable
或者 Vector 或者返回的迭代器 – 由這些類返回的 fail-fast
迭代器假定在迭代器進行遍歷的時候底層集合不會有變化。為了保證其他線程不會在遍歷的時候改變集合,進行迭代的線程應該確保它是獨占性地訪問集合以實現遍歷的完整性。通常,獨占性的訪問是由對鎖的同步保證的
– 並且類的文檔應該說明是哪個鎖(通常是對象的內部監視器(intrinsic monitor))。
如果對一個有條件線程安全類進行記錄,那麼您應該不僅要記錄它是有條件線程安全的,而且還要記錄必須防止哪些操作序列的並發訪問。用戶可以合理地假設其他操作序列不需要任何額外的同步。
線程兼容
線程兼容類不是線程安全的,但是可以通過正確使用同步而在並發環境中安全地使用。這可能意味著用一個 synchronized
塊包圍每一個方法調用,或者創建一個包裝器對象,其中每一個方法都是同步的(就像 Collections.synchronizedList()
一樣)。也可能意味著用 synchronized
塊包圍某些操作序列。為了最大程度地利用線程兼容類,如果所有調用都使用同一個塊,那麼就不應該要求調用者對該塊同步。這樣做會使線程兼容的對象作為變數實例包含在其他線程安全的對象中,從而可以利用其所有者對象的同步。
許多常見的類是線程兼容的,如集合類 ArrayList 和 HashMap 、 java.text.SimpleDateFormat 、或者 JDBC 類 Connection 和 ResultSet 。
線程對立
線程對立類是那些不管是否調用了外部同步都不能在並發使用時安全地呈現的類。線程對立很少見,當類修改靜態數據,而靜態數據會影響在其他線程中執行的其他類的行為,這時通常會出現線程對立。線程對立類的一個例子是調用 System.setOut() 的類。

⑦ 【集合】List、Map、Set部分實現類是否線程安全

1.1 ArrayList 不是線程安全的。多線程情況下操作ArrayList 不是線性安全的,可能會拋出 java.util. 並發修改異常。
1.2 Vector 是線程安全的。Vector對add和get方法都加了關鍵字synchronized修飾,所以是線程安全的,但是同一時間只能有一個線程訪問進行讀寫,所以性能慢。

1.3 Collections.synchronizedList(List<T> list) 通過Collections的synchronizedList靜態方法,可以返歸一個線程安全的SynchronizedList對象。SynchronizedList是Collections的靜態內部類。

synchronizedLis 和 Vector的區別

1.4 CopyOnWriteArrayList<E> 寫入時復制(CopyOnWrite)思想
數據存放在一個Object數組中,在進行add和set操作時會上鎖,同時一份原始的Object數組,在完成add和set操作後,重新setArray,釋放鎖。get操作沒有加鎖,如果讀的時候有多個線程正在向CopyOnWriteArrayList添加數據,不會阻塞,讀還是可以讀到舊的數據。

一個測試各種List是否安全的例子:

2.1 HashMap<> 不是線程安全的。多線程情況下操作HashMap不是線性安全的,可能會拋出 java.util. 並發修改異常。
  HashMap就有點復雜了,1.7由數組+鏈表實現,1.8由數組+鏈表+紅黑樹實現,不深入了,得單獨學。
2.2 Collections.synchronizedMap( new HashMap<>()) 通過Collections的synchronizedMap靜態方法,可以返歸一個線程安全的SynchronizedMap對象。SynchronizedMap是Collections的靜態內部類。 get和put都加鎖

2.3 class ConcurrentHashMap<K,V> 來自 java.util.concurrent.ConcurrentHashMap,支持檢索的完全並發性和更新的高預期並發性的哈希表,單獨學。
一個測試各種Map是否安全的例子:

3.1 class HashSet<E> 不是線程安全的。
  HashSetd底層由HashMap實現,HashSet的add方法調用對的是HashMap的put方法,傳輸的key是將傳入set的元素,傳入的value是一個固定的Object對象。

3.2 class TreeSet<E> 不是線程安全的。
3.3 Collections.synchronizedSet(new HashSet<>()) 是線程安全的。
3.4 class CopyOnWriteArraySet<E> 是線程安全的。
一個測試各種Set是否安全的例子:

⑧ Java集合中哪些類是線程安全的

線程安全類

在集合框架中,有些類是線程安全的,這些都是jdk1.1中的出現的。在jdk1.2之後,就出現許許多多非線程安全的類。 下面是這些線程安全的同步的類:

vector:就比arraylist多了個同步化機制(線程安全),因為效率較低,現在已經不太建議使用。在web應用中,特別是前台頁面,往往效率(頁面響應速度)是優先考慮的。

statck:堆棧類,先進後出

hashtable:就比hashmap多了個線程安全

enumeration:枚舉,相當於迭代器

除了這些之外,其他的都是非線程安全的類和介面。

線程安全的類其方法是同步的,每次只能一個訪問。是重量級對象,效率較低。

其他:

1. hashtable跟hashmap的區別

hashtable是線程安全的,即hashtable的方法都提供了同步機制;hashmap不是線程安全的,即不提供同步機制 ;hashtable不允許插入空值,hashmap允許!

2. 多線程並發修改一 個 集合 怎麼辦

用老的Vector/Hashtable類

StringBuffer是線程安全,而StringBuilder是線程不安全的。對於安全與不安全沒有深入的理解情況下,易造成這樣的錯覺,如果對於StringBuffer的操作均是線程安全的,然而,Java給你的保證的線程安全,是說它的方法是執行是排它的,而不是對這個對象本身的多次調用情況下,還是安全的。看看下邊的例子,在StringBufferTest中有一個數據成員contents它是用來擴展的,它的每一次append是線程安全的,但眾多次append的組合並不是線程安全的,這個輸出結果不是太可控的,但如果對於log和getContest方法加關鍵字synchronized,那麼結果就會變得非常條理,如果換成StringBuider甚至是append到一半,它也會讓位於其它在此基礎上操作的線程:

⑨ 如何確保Java線程安全

在Java中可以有很多方法來保證線程安全——同步,使用原子類(atomicconcurrentclasses),實現並發鎖,使用volatile關鍵字,使用不變類和線程安全類。

閱讀全文

與java線程安全set相關的資料

熱點內容
德國愛情電影推薦 瀏覽:859
好看的,每天更新的網址推薦 瀏覽:910
五行拳電影 瀏覽:788
wolfram編程 瀏覽:140
蜘蛛有哪幾種類動畫片? 瀏覽:852
韓劇這個男的和三姐妹都有關系 瀏覽:847
電影中的大奶的視頻 瀏覽:178
日本電影一個女的乳頭被切掉了 瀏覽:268
看電影男朋友聽我心跳 瀏覽:494
cudac語言編程指南 瀏覽:856
小說女主被男主囚禁各種逃跑 瀏覽:722
重生在黃埔一期參加北伐的小說 瀏覽:88
韓國床戲電影合集 瀏覽:199
好看的快穿肉文 瀏覽:512
曼曼雅朵小仙兒有聲小說 瀏覽:298
sci謎案集未刪改資源 瀏覽:94
編譯的字體顏色怎麼調 瀏覽:118
黛妃作品集txt下書網 瀏覽:867
jdk6源碼編譯 瀏覽:11