同步类容器:同步类容器都是线程安全的,但在某些场景下需要加锁来保证复合操作,复合操作指:迭代(遍历)、查询(根据指定顺序根据当前元素找到下一个元素、跳转)、以及条件运算
例如:在容器迭代的过程中,容器被并发的修改了内容
package com.neo.study001.radio10;
import java.util.ArrayList;
import java.util.Iterator;
/**
* @author liyy
* @date 2020/4/23 22:58
* @Function 将“先检查后执行”以及“读取——修改——写入”等操作统称为复合操作
*/
public class FuHeCaoZuo {
static ArrayList<Integer> list = new ArrayList<Integer>();
public static void main(String[] args) {
list.add(1);
list.add(2);
list.add(3);
list.add(4);
list.add(5);
Thread thread1 = new Thread(new Runnable() {
@Override
public void run() {
Iterator<Integer> iterator = list.iterator();
while (iterator.hasNext()) {
Integer integer = iterator.next();
System.out.println("当前元素的值:" + integer);
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}, "t1");
Thread thread2 = new Thread(new Runnable() {
@Override
public void run() {
Iterator<Integer> iterator = list.iterator();
while (iterator.hasNext()) {
Integer integer = iterator.next();
if (integer == 2)
iterator.remove();
}
}
}, "t2");
thread1.start();
thread2.start();
}
}
常见同步类容器:Vector,HashTable等,同步功能的实现底层使用的是Collections.synchronized****工厂方法实现的,对每个公用的方法进行同步,保证在多线程环境下只能有一个线程访问容器状态,实现同步.
package com.neo.study001.radio10;
import org.junit.Test;
import java.util.*;
/**
* @author liyy
* @date 2020/4/24 23:09
*/
public class CheckHashMapAndHashTable {
public static void testList() {
List<String> list = new ArrayList<String>();
for (int i = 0; i < 10; i++) {
new Thread(new Runnable() {
@Override
public void run() {
list.add(UUID.randomUUID().toString().substring(0, 8));
System.out.println(Thread.currentThread().getName() + "\t" + list);
}
}, "t" + i).start();
}
}
public static void testVector() {
Vector<String> list = new Vector<String>();
for (int i = 0; i < 10; i++) {
new Thread(new Runnable() {
@Override
public void run() {
list.add(UUID.randomUUID().toString().substring(0, 8));
System.out.println(Thread.currentThread().getName() + "\t" + list);
}
}, "t" + i).start();
}
}
public static void testMap() throws Exception {
final int N = 5;
final HashMap<String, Integer> mapTest = new HashMap<String, Integer>();
final List<Thread> threadList = new ArrayList<Thread>(N);
for (int i = 0; i < N; i++) {
threadList.add(new Thread(() -> {
for (int j = 0; j < 10000; j++) {
mapTest.put(Thread.currentThread().getId() + "key" + j, j);
}
}));
}
for (Thread thread : threadList) {
thread.start();
}
for (Thread thread : threadList) {
thread.join();
}
System.out.println(mapTest.size());
}
public static void testCollectionsSynchronized() throws Exception{
final int N = 5;
Map<String, Integer> mapTest = Collections.synchronizedMap(new HashMap<String, Integer>());
//final HashMap<String, Integer> mapTest = new HashMap<String, Integer>();
final List<Thread> threadList = new ArrayList<Thread>(N);
for (int i = 0; i < N; i++) {
threadList.add(new Thread(() -> {
for (int j = 0; j < 10000; j++) {
mapTest.put(Thread.currentThread().getId() + "key" + j, j);
}
}));
}
for (Thread thread : threadList) {
thread.start();
}
for (Thread thread : threadList) {
thread.join();
}
System.out.println(mapTest.size());
}
public static void testTable() throws Exception {
final int N = 5;
final Hashtable<String, Integer> mapTest = new Hashtable<String, Integer>();
final List<Thread> threadList = new ArrayList<Thread>(N);
for (int i = 0; i < N; i++) {
threadList.add(new Thread(() -> {
for (int j = 0; j < 10000; j++) {
mapTest.put(Thread.currentThread().getId() + "key" + j, j);
}
}));
}
for (Thread thread : threadList) {
thread.start();
}
for (Thread thread : threadList) {
thread.join();
}
System.out.println(mapTest.size());
}
public static void main(String[] args) throws Exception {
// testList();//多次执行会抛出异常
// testVector();//多次执行不会抛出异常
// testMap();//最后的结果不一定是50000
//testTable();//最后的结果一定是50000
testCollectionsSynchronized();
}
}
并发类容器:同步类容器虽然实现了线程的安全,但加锁串行化的方式严重降低了并发性,多线程环境下降低了应用程序的吞吐量,因此就有了并发类容器
常见的并发类容器:ConcurrentHashMap代替了给与散列传统的HashTable,还有CopyOnWriteArrayList代替了Vector,还有并发的CopyOnWriteArraySet,以及并发的Queue,ConcurrentLinkedQueue,LinkedBlockingQueue等