Ⅰ java arryList 線程安全問題
在Collections工具抄類中有這樣的方法:
static <T> List<T> synchronizedList(List<T> list) 返回線程安全的集合
還有這種的set maP的你看看API文檔
Ⅱ java中Arraylist是干什麼的怎麼用
java中的ArrayList就是傳說中的動態數組,用MSDN中的說法,就是Array的復雜版本。
它提供了如下一些好處:動態的增加和減少元素實現了ICollection和IList介面靈活的設置數組的大小 。
ArrayList 的用法:
ArrayList List = new ArrayList(); for( int
i=0;i<10;i++ ) //
給數組增加10個Int元素 List.Add(i); //..
程序做一些處理
List.RemoveAt(5);//
將第6個元素移除 for( int i=0;i<3;i++ ) //
再增加3個元素
List.Add(i+20); Int32[] values =
(Int32[])List.ToArray(typeof(Int32));//
返回ArrayList包含的數組 。
(2)array線程安全java擴展閱讀:
Arraylist的定義:
List 介面的大小可變數組的實現,位於API文檔的java.util.ArrayList<E>。
實現了所有可選列表操作,並允許包括 null 在內的所有元素。
除了實現 List 介面外,此類還提供一些方法來操作內部用來存儲列表的數組的大小。(此類大致上等同於 Vector 類,除了此類是不同步的。)
size、isEmpty、get、set、iterator 和 listIterator 操作都以固定時間運行。
add 操作以分攤的固定時間 運行,也就是說,添加 n 個元素需要 O(n) 時間。
其他所有操作都以線性時間運行(大體上講)。
與用於 LinkedList 實現的常數因子相比,此實現的常數因子較低。
每個 ArrayList 實例都有一個容量。該容量是指用來存儲列表元素的數組的大小。
它總是至少等於列表的大小。隨著向 ArrayList 中不斷添加元素,其容量也自動增長。
並未指定增長策略的細節,因為這不只是添加元素會帶來分攤固定時間開銷那樣簡單
在添加大量元素前,應用程序可以使用
ensureCapacity 操作來增加 ArrayList
實例的容量。這可以減少遞增式再分配的數量。
注意,此實現不是同步的。如果多個線程同時訪問一個 ArrayList
實例,而其中至少一個線程從結構上修改了列表,那麼它必須 保持外部同步。
(結構上的修改是指任何添加或刪除一個或多個元素的操作,或者顯式調整底層數組的大小;僅僅設置元素的值不是結構上的修改。)
這一般通過對自然封裝該列表的對象進行同步操作來完成。
如果不存在這樣的對象,則應該使用 Collections.synchronizedList 方法將該列表「包裝」起來。這最好在創建時完成,以防止意外對列表進行不同步的訪問:
List list = Collections.synchronizedList(new ArrayList(...));
此類的 iterator 和 listIterator 方法返回的迭代器是快速失敗的。
在創建迭代器之後,除非通過迭代器自身的
remove 方法從結構上對列表進行修改,否則在任何時間以任何方式對列表進行修改,迭代器都會拋出
。
因此,面對並發的修改,迭代器很快就會完全失敗,而不是冒著在將來某個不確定時間發生任意不確定行為的風險。
注意,迭代器的快速失敗行為無法得到保證。
因為一般來說,不可能對是否出現不同步並發修改做出任何硬性保證。快速失敗迭代器會盡最大努力拋出
。
因此,為提高這類迭代器的正確性而編寫一個依賴於此異常的程序是錯誤的做法:迭代器的快速失敗行為應該僅用於檢測
bug。
Ⅲ java里,數組,線程安全的和不安全的,是什麼意思
比如說,兩個線程操作同一個ArrayList變數,那麼一個線程這一時刻讀的數據可能在下一刻要改變。
一般在類似於下內面的情景下考慮線程安全的問題:
ArrayList procts=new ArrayList ();
procts用來存放生產出來的產品。
現在假設:有3個消費者線程,2個生產者線程。
每個生產者線程生產出一個產品,執行
procts.add(new Proct());
每個消費者線程消費一個產品執行
if(procts.size()>=1){ procts.remove(0);}
如果procts里現在只有一個產品可以消費,但是有2個消費者線程請求消費,那麼就有可能出現一個產品被同時消費的問題,而這是和實際不符的。
但是不同的線程訪問Vector的時候不會發生這種錯誤,因為java會有相應的機制是同一時刻只有一個線程對這個變容量操作。
這就是所謂的:
Vector:是線程安全的
ArrayList:不是線程安全的
Ⅳ arraylist是線程安全的嗎
是不安全的,你可以參考如下內容:
用ArrayList時,出現如下錯誤:
Exception in thread "Thread-1" java.lang.: 452
at java.util.ArrayList.add(ArrayList.java:352)
改為List list=Collections.synchronizedList(new ArrayList())之後,就正常了。
List<Map<String,Object>> data=new ArrayList<Map<String,Object>>();
那麼為了解決這個線程安全問前搏題你可以這么使用Collections.synchronizedList(),如:
List<Map<String,Object>> data=Collections.synchronizedList(new ArrayList<Map<String,Object>>());
其他的都沒變,使用的方法也幾乎與ArrayList一樣,大家可以參考下api文檔;
額外說下 ArrayList與LinkedList;這兩個都是介面List下的一個實現,用法都一樣,但用的場所的有點不同,ArrayList適合於進行大量的隨機訪問的情況下使用,LinkedList適合在表中進行插入、刪除時使用,二者都是非線程安全,解決方法同上(為了避慧碰祥吵孝免線程安全,以上採取的方法,特別是第二種,其實是非常損耗性能的)。
Ⅳ Java中StringBuffer 、ArrayList是線程安全的嗎
ArrayList不是線程安全的
你看API如果他們的方法定義裡面有synchronized證明是線程安全的
StringBuffer是線程安全的
Ⅵ 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的集合工具類在添加方面更加快一些,其他方法這里篇幅關系就不測試了,大家有興趣去試一下。
Ⅶ Java的List如何實現線程安全
零基礎學習java可按照這份大綱來進行學習
第一階段:Java專業基礎課程
階段目標:
1. 熟練掌握Java的開發環境與編程核心知識
2. 熟練運用Java面向對象知識進行程序開發
3. 對Java的核心對象和組件有深入理解
4. 熟練應用JavaAPI相關知識
5. 熟練應用JAVA多線程技術
6. 能綜合運用所學知識完成一個項目
知識點:
1、基本數據類型,運算符,數組,掌握基本數據類型轉換,運算符,沖配流程式控制制。
2、數組,排序演算法,Java常用API,類和對象,了解類與對象,熟悉常用API。
3、面向對象特性,集合框架,熟悉祥判御面向對象三大特性,熟練使用集合框架。
4、IO流,多線程。
5、網路協議,線程運用。
第二階段:JavaWEB核心課程
階段目標:
1. 熟練掌握資料庫和MySQL核心技術
2. 深入理解JDBC與DAO資料庫操作
3. 熟練運用JSP及Servlet技術完成網站後台開發
4. 深入理解緩存,連接池,註解,反射,泛型等知識
5. 能夠運用所學知識完成自定義框架
知識點:
1、資料庫知識,範式,MySQL配置,命令,建庫建表,數據的增刪改查,約束,視圖,存儲過程,函數,觸發器,事務,游標,建模工具。
2、深入理解資料庫管理系統通用知識及MySQL資料庫的使用與管理。為Java後台開發打下堅實基礎。Web頁面元素,布局,CSS樣式,盒模型,JavaScript,jQuery。
3、掌握前端開發技術,掌握jQuery。
4、Servlet,EL表達式,會話跟蹤技術,過濾器,FreeMarker。
5、掌握Servlet相關技術,利用Servlet,JSP相關應用技術和DAO完成B/S架構下的應用開發。
6、泛型,反射,註解。
7、掌握JAVA高級應用,利用泛型,註解,枚舉完成自己的CRUD框謹岩架開發為後續框架學習做鋪墊。
8、單點登錄,支付功能,項目整合,分頁封裝熟練運用JSP及Servlet核心知識完成項目實戰。
第三階段:JavaEE框架課程
階段目標:
1. 熟練運用Linux操作系統常見命令及完成環境部署和Nginx伺服器的配置
2. 熟練運用JavaEE三大核心框架:Spring,SpringMVC,MyBatis
3. 熟練運用Maven,並使用SpringBoot進行快速框架搭建
4. 深入理解框架的實現原理,Java底層技術,企業級應用等
5. 使用Shiro,Ztree和Spring,SpringMVC,Myts完成企業項目
知識點:
1、Linux安裝配置,文件目錄操作,VI命令,管理,用戶與許可權,環境部署,Struts2概述,hiberante概述。
2、Linux作為一個主流的伺服器操作系統,是每一個開發工程師必須掌握的重點技術,並且能夠熟練運用。
3、SSH的整合,MyBatis,SpringMVC,Maven的使用。
4、了解AOP原理,了解中央控制器原理,掌握MyBatis框架,掌握SSM框架的整合。
5、Shiro,Ztree,項目文檔,項目規范,需求分析,原型圖設計,資料庫設計,工程構建,需求評審,配置管理,BUG修復,項目管理等。
6、獨立自主完成一個中小型的企業級綜合項目的設計和整體架構的原型和建模。獨立自主完成一個大型的企業級綜合項目,並具備商業價值