Collection体系集合、以及线程安全集合。
注:下划线代表线程安全集合
Collections工具类中提供了多个可以获得线程安全集合的方法。
- public static Collection synchronizedCollection(Collection c)
- public static List synchronizedList(List list)
- public static Set synchronizedSet(Set s)
- public static <K,V> Map<K,V> synchronizedMap(Map<K,V> m)
- public static SortedSet synchronizedSortedSet(SortedSet s)
- public static <K,V> SortedMap<K,V> synchronizedSortedMap(SortedMap<K,V> m)
JDK1.2提供,接口统一、维护性高,但性能没有提升,均以synchonized实现。
JDK 1.7
JDK 1.8
eg:
public class TestThreadSafe {
public static void main(String[] args) {
//ArrayList<String> list=new ArrayList<>();
//CopyOnWriteArrayList list=new CopyOnWriteArrayList();
//CopyOnWriteArraySet set=new CopyOnWriteArraySet();
ConcurrentHashMap<String,String> hashMap=new ConcurrentHashMap<>();
ExecutorService es = Executors.newFixedThreadPool(10);
for (int i = 0; i < 10; i++) {
es.submit(new Runnable() {
@Override
public void run() {
for (int j = 0; j < 10; j++) {
try {
Thread.sleep(100);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
hashMap.put(Thread.currentThread().getName()+"..."+j,"xxx");
}
}
});
}
es.shutdown();
while(!es.isTerminated());
System.out.println("元素个数:"+hashMap.size());
}
}
CAS:Compare And Swap(比较交换算法)
乐观锁:
- 总是认为是线程安全,不怕别的线程修改变量,如果修改了再重新尝试,直到成功。
- CAS是乐观锁。
悲观锁:
- 总是认为线程不安全,不管什么情况都进行加锁,要是获取锁失败,就阻塞。
- synchronized、ReentrantLock是悲观锁。
CAS比较交换算法,修改的方法包含三个核心参数(V,E,N)
eg:
使用代码模拟CAS算法
public class TestCAS {
public static void main(String[] args) {
Cas cas=new Cas();
ExecutorService es = Executors.newFixedThreadPool(100);
for (int i = 0; i < 100; i++) {
es.submit(() -> {
while(true) {
int old = cas.getV();
boolean b = cas.compareAndSwap(old, new Random().nextInt(100));
System.out.println(Thread.currentThread().getName()+"..."+b);
if(b){
break;
}
}
});
}
es.shutdown();
}
static class Cas{
private int V;//更新的变量
//获取V的值
public int getV(){
return V;
}
public synchronized boolean compareAndSwap(int E,int N){
if(E==V){
V=N;
return true;
}
return false;
}
}
}
Collection的子接口,表示队列FIFO(First In First Out)
常用方法:
线程安全、可高效读写的队列,高并发下性能最好的队列。
eg:
public class TestQueue {
public static void main(String[] args) {
// Queue<String> queue=new LinkedList<>();
Queue<String> queue=new ConcurrentLinkedQueue<>();
//入队
// queue.offer("aaa");
// queue.offer("bbb");
// queue.offer("ccc");
ExecutorService es = Executors.newFixedThreadPool(3);
for (int i = 0; i < 3; i++) {
es.submit(new Runnable() {
@Override
public void run() {
queue.offer(Thread.currentThread().getName());
}
});
}
//出队
es.shutdown();
while(!es.isTerminated());
int count=queue.size();
for (int i = 0; i < count; i++) {
System.out.println(queue.poll());
}
}
}
Queue的子接口,阻塞的队列,增加了两个线程状态为无限期等待的方法。
方法:
实现类:
eg:
package StageOne.day21.demo02;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.LinkedBlockingQueue;
/**
* @author 胡昊龙
* @version 1.0
* @description: TODO
* @date 2024/1/16 14:32
*/
public class TestBlockingQueue {
public static void main(String[] args) {
//创建阻塞队列
BlockingQueue<String> queue = new LinkedBlockingQueue<>(6);
//创建线程池
ExecutorService es = Executors.newCachedThreadPool();
//提交任务
es.submit(()->{
for (int i = 0; i < 30; i++) {
try {
queue.put("面包"+i);
System.out.println("生产了"+i);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
}
});
es.submit(()->{
for (int i = 0; i < 30; i++) {
try {
String take = queue.take();
System.out.println("消费了"+take);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
}
});
es.shutdown();
}
}