java併發數據結構
- 常用的數據結構是線程不安全的
– ArrayList,HashMap, HashSet非同步的,這些在多線程中是不適用的
– 多個線程同時讀寫,可能會拋出異常或數據錯誤
- 傳統Vector,Hashtable等同步集合性能過差
- 併發數據結構:數據添加和刪除
– 阻塞式集合:當集合爲空或者滿時,等待
– 非阻塞式集合:當集合爲空或者滿時,不等待,返回null或異常
- List
– Vector 同步安全,寫多讀少
– ArrayList 不安全
– Collections.synchronaizedList(List list) 基於synchronized,效率差,線程安全
– CopyOnWriteArrayList 適合讀多寫少,基於複製機制,非阻塞,性能比較好(JDK 5)
- Set
– HashSet 不安全
– Collectionss.synchronizedSet(Set set) 基於synchronized,效率差,線程安全
– CopyOnWriteArraySet(基於CopyOnWriteArrayList實現) 讀多寫少,非阻塞,線程安全
- Map
– Hashtable 同步安全,寫多讀少,性能不是很好
– HashMap 不安全
– Collections.synchronizedMap(Map map) 基於synchronized, 效率差
– ConcurrentHashMap 讀多寫少,非阻塞
- Queue & Deque(隊列,JDK1.5提出)
– ConcurrentLinkedQueue 非阻塞
– ArrayBlockingQueue/LinkedBlockingQueue 阻塞
synchronized所包圍的代碼,一次只能由一個線程來執行。
Deque 是雙向隊列,兩頭都可以插入元素
list代碼示例:
package com.torey;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.concurrent.CopyOnWriteArrayList;
public class ListTest {
public static void main(String[] args) {
List<String> unsafeList=new ArrayList<>();
List<String> safeList= Collections.synchronizedList(new ArrayList<String>());
CopyOnWriteArrayList<String> copySafeList=new CopyOnWriteArrayList<>();
ListThread t1 = new ListThread(unsafeList);
ListThread t2 = new ListThread(safeList);
ListThread t3 = new ListThread(copySafeList);
for (int i = 0; i < 10; i++) {
new Thread(t1,String.valueOf(i)).start();
new Thread(t2,String.valueOf(i)).start();
new Thread(t3,String.valueOf(i)).start();
}
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("t1:"+t1.list.size());
System.out.println("t2:"+t2.list.size());
System.out.println("t3:"+t3.list.size());
System.out.println("unsafeList:");
for (String s : t1.list) {
System.out.print(s + " ");
}
System.out.println();
System.out.println("safeList:");
for (String s : t2.list) {
System.out.print(s + " ");
}
System.out.println();
System.out.println("copySafeList:");
for (String s : t3.list) {
System.out.print(s + " ");
}
}
}
class ListThread implements Runnable{
public List<String> list;
public ListThread(List<String> list) {
this.list = list;
}
@Override
public void run() {
int i=0;
while (i<10){
try {
Thread.sleep(10);
} catch (InterruptedException e) {
e.printStackTrace();
}
list.add(Thread.currentThread().getName());
i++;
}
}
}
set代碼示例:
package com.torey;
import java.util.Collections;
import java.util.HashSet;
import java.util.Set;
import java.util.concurrent.CopyOnWriteArraySet;
public class SetTest {
public static void main(String[] args){
Set<String> unsafeSet=new HashSet<>();
Set<String> safeSet= Collections.synchronizedSet(new HashSet<>());
CopyOnWriteArraySet<String> safeSet2 = new CopyOnWriteArraySet<>();
SetThread set1 = new SetThread(unsafeSet);
SetThread set2 = new SetThread(safeSet);
SetThread set3 = new SetThread(safeSet2);
for (int i = 0; i < 10; i++) {
new Thread(set1,String.valueOf(i)).start();
new Thread(set2,String.valueOf(i)).start();
new Thread(set3,String.valueOf(i)).start();
}
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("set1="+set1.setTest.size());
System.out.println("set2="+set2.setTest.size());
System.out.println("set3="+set3.setTest.size());
System.out.println("unsafeList:");
for (String s : set1.setTest) {
System.out.print(s + " ");
}
System.out.println();
System.out.println("safeList:");
for (String s : set2.setTest) {
System.out.print(s + " ");
}
System.out.println();
System.out.println("copySafeList:");
for (String s : set3.setTest) {
System.out.print(s + " ");
}
}
}
class SetThread implements Runnable{
public Set<String> setTest;
public SetThread(Set<String> setTest) {
this.setTest = setTest;
}
@Override
public void run() {
int i=0;
while (i<10){
i++;
try {
Thread.sleep(10);
} catch (InterruptedException e) {
e.printStackTrace();
}
setTest.add(Thread.currentThread().getName()+i);
}
}
}
map示例:
package com.torey;
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
public class MapTest {
public static void main(String[] args){
Map<String,Integer> mapTest=new HashMap<>();
Map<String, Integer> synchronizedMap = Collections.synchronizedMap(new HashMap<String, Integer>());
ConcurrentHashMap<String,Integer> concurrentHashMap=new ConcurrentHashMap<>();
MapThread mapThread = new MapThread(mapTest);
MapThread synchronizedMapThread= new MapThread(synchronizedMap);
MapThread concurrentHashMapThread = new MapThread(concurrentHashMap);
for (int i = 0; i < 10; i++) {
new Thread(mapThread).start();
new Thread(synchronizedMapThread).start();
new Thread(concurrentHashMapThread).start();
}
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(mapThread.mapList.size());
System.out.println(synchronizedMapThread.mapList.size());
System.out.println(concurrentHashMapThread.mapList.size());
System.out.println("mapThread:");
for (String s : mapThread.mapList.keySet()) {
System.out.print(mapThread.mapList.get(s) + " ");
}
System.out.println();
System.out.println("synchronizedMapThread:");
for (String s : synchronizedMapThread.mapList.keySet()) {
System.out.print(synchronizedMapThread.mapList.get(s) + " ");
}
System.out.println();
System.out.println("concurrentHashMapThread:");
for (String s : concurrentHashMapThread.mapList.keySet()) {
System.out.print(concurrentHashMapThread.mapList.get(s) + " ");
}
}
}
class MapThread implements Runnable{
public Map<String,Integer> mapList;
public MapThread(Map<String, Integer> mapList) {
this.mapList = mapList;
}
@Override
public void run() {
int i=0;
while (i<10){
i++;
try {
Thread.sleep(10);
} catch (InterruptedException e) {
e.printStackTrace();
}
mapList.put(Thread.currentThread().getName()+i,i);
}
}
}
Queue多線程測試
package com.torey;
import java.util.ArrayDeque;
import java.util.Deque;
import java.util.Queue;
import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.ConcurrentLinkedDeque;
public class QueueTest {
public static void main(String[] args) throws InterruptedException {
Deque<String> unsafeQueue=new ArrayDeque<>();
ConcurrentLinkedDeque<String> safeQueue1=new ConcurrentLinkedDeque<String>();
ArrayBlockingQueue<String> safeQueue2=new ArrayBlockingQueue<>(100);
QueueThread t1 = new QueueThread(unsafeQueue);
QueueThread t2 = new QueueThread(safeQueue1);
QueueThread t3 = new QueueThread(safeQueue2);
for (int i = 0; i < 10; i++) {
new Thread(t1,String.valueOf(i)).start();
new Thread(t2,String.valueOf(i)).start();
new Thread(t3,String.valueOf(i)).start();
}
Thread.sleep(2000);
System.out.println("t1.queue.size()" + t1.queue.size());
System.out.println("t2.queue.size()" + t2.queue.size());
System.out.println("t3.queue.size()" + t3.queue.size());
System.out.println("t1:");
for (String s : t1.queue) {
System.out.print(s + " ");
}
System.out.println();
System.out.println("t2:");
for (String s : t2.queue) {
System.out.print(s + " ");
}
System.out.println();
System.out.println("t3:");
for (String s : t3.queue) {
System.out.print(s + " ");
}
}
}
class QueueThread implements Runnable{
public Queue<String> queue;
public QueueThread(Queue<String> queue) {
this.queue = queue;
}
@Override
public void run() {
int i=0;
while (i<10){
i++;
try {
Thread.sleep(10);
} catch (InterruptedException e) {
e.printStackTrace();
}
queue.add(Thread.currentThread().getName());
}
}
}