【Java】Java并发容器J.U.C
CopyOnWriteArrayList
介绍
public boolean add(E e) {final ReentrantLock lock = this.lock;
lock.lock(); //加锁
try {
Object[] elements = getArray();
int len = elements.length;
Object[] newElements = Arrays.copyOf(elements, len + 1);
newElements[len] = e;
//引用指向更改
setArray(newElements);
return true;
} finally {
lock.unlock(); //释放锁
}
}
public E get(int index) {return get(getArray(), index);
}
- 如果写操作未完成,那么直接读取原数组的数据;
- 如果写操作完成,但是引用还未指向新数组,那么也是读取原数组数据;
- 如果写操作完成,并且引用已经指向了新的数组,那么直接从新数组中读取数据。
CopyOnWriteArrayList
多线程代码演示。
package com.rumenz.task;import java.util.List;
import java.util.concurrent.*;
//线程安全
public class CopyOnWrireArrayListExample {
public static Integer clientTotal=5000;
public static Integer threadTotal=200;
private static List<Integer> list=new CopyOnWriteArrayList();
public static void main(String[] args) throws Exception{
ExecutorService executorService = Executors.newCachedThreadPool();
final Semaphore semaphore=new Semaphore(threadTotal);
final CountDownLatch countDownLatch=new CountDownLatch(clientTotal);
for (int i = 0; i < clientTotal; i++) {
final Integer j=i;
executorService.execute(()->{
try{
semaphore.acquire();
update(j);
semaphore.release();
}catch (Exception e){
e.printStackTrace();
}
countDownLatch.countDown();
});
}
countDownLatch.await();
executorService.shutdown();
System.out.println("size:"+list.size());
}
private static void update(Integer j) {
list.add(j);
}
}
//size:5000
CopyOnWriteArrayList
使用场景
- 由于在
add
的时候需要拷贝原数组,如果原数组内容比较多,比较大,可能会导致young gc
和full gc
。 - 不能用于实时读的场景,像拷贝数组,新增元素都需要时间,所以调用
get
操作后,有可能得到的数据是旧数据,虽然CopyOnWriteArrayList
能做到最终一致性,但是没有办法满足实时性要求。 CopyOnWriteArrayList
适合读多写少的场景,比如白名单,黑名单等场景CopyOnWriteArrayList
由于add
时需要复制数组,所以不适用高性能的互联网的应用。
CopyOnWriteArraySet
介绍
public CopyOnWriteArraySet() {al = new CopyOnWriteArrayList<E>();
}
CopyOnWriteArraySet
多线代码演示
package com.rumenz.task;import java.util.List;
import java.util.Set;
import java.util.concurrent.*;
//线程安全
public class CopyOnWrireArraySetExample {
public static Integer clientTotal=5000;
public static Integer threadTotal=200;
private static Set<Integer> set=new CopyOnWriteArraySet();
public static void main(String[] args) throws Exception{
ExecutorService executorService = Executors.newCachedThreadPool();
final Semaphore semaphore=new Semaphore(threadTotal);
final CountDownLatch countDownLatch=new CountDownLatch(clientTotal);
for (int i = 0; i < clientTotal; i++) {
final Integer j=i;
executorService.execute(()->{
try{
semaphore.acquire();
update(j);
semaphore.release();
}catch (Exception e){
e.printStackTrace();
}
countDownLatch.countDown();
});
}
countDownLatch.await();
executorService.shutdown();
System.out.println("size:"+set.size());
}
private static void update(Integer j) {
set.add(j);
}
}
//size:5000
CopyOnWriteArraySet
使用场景
- 适用于set大小一般很小,读操作远远多于写操作的场景
ConcurrentSkipListSet
public ConcurrentSkipListSet() {m = new ConcurrentSkipListMap<E,Object>();
}
public boolean addAll(Collection<? extends E> c) {boolean modified = false;
for (E e : c)
if (add(e))
modified = true;
return modified;
}
public boolean removeAll(Collection<?> c) {
Objects.requireNonNull(c);
boolean modified = false;
Iterator<?> it = iterator();
while (it.hasNext()) {
if (c.contains(it.next())) {
it.remove();
modified = true;
}
}
return modified;
}
public boolean containsAll(Collection<?> c) {
for (Object e : c)
if (!contains(e))
return false;
return true;
}
ConcurrentSkipListSet
代码演示
package com.rumenz.task;import java.util.ArrayList;
import java.util.List;
import java.util.Set;
import java.util.concurrent.*;
//线程安全
public class CopyOnWrireArrayListExample {
public static Integer clientTotal=5000;
public static Integer threadTotal=200;
private static Set<Integer> set= new ConcurrentSkipListSet();
public static void main(String[] args) throws Exception{
ExecutorService executorService = Executors.newCachedThreadPool();
final Semaphore semaphore=new Semaphore(threadTotal);
final CountDownLatch countDownLatch=new CountDownLatch(clientTotal);
for (int i = 0; i < clientTotal; i++) {
final Integer j=i;
executorService.execute(()->{
try{
semaphore.acquire();
update(j);
semaphore.release();
}catch (Exception e){
e.printStackTrace();
}
countDownLatch.countDown();
});
}
countDownLatch.await();
executorService.shutdown();
System.out.println("size:"+set.size());
}
private static void update(Integer r) {
set.add(r);
}
}
//size:5000
ConcurrentHashMap
ConcurrentHashMap
代码演示案例
package com.rumenz.task;import java.util.Map;
import java.util.Set;
import java.util.concurrent.*;
//线程安全
public class ConcurrentHashMapExample {
public static Integer clientTotal=5000;
public static Integer threadTotal=200;
private static Map<Integer,Integer> map=new ConcurrentHashMap<Integer,Integer>();
public static void main(String[] args) throws Exception{
ExecutorService executorService = Executors.newCachedThreadPool();
final Semaphore semaphore=new Semaphore(threadTotal);
final CountDownLatch countDownLatch=new CountDownLatch(clientTotal);
for (int i = 0; i < clientTotal; i++) {
final Integer j=i;
executorService.execute(()->{
try{
semaphore.acquire();
update(j);
semaphore.release();
}catch (Exception e){
e.printStackTrace();
}
countDownLatch.countDown();
});
}
countDownLatch.await();
executorService.shutdown();
System.out.println("size:"+map.size());
}
private static void update(Integer j) {
map.put(j, j);
}
}
//size:5000
ConcurrentSkipListMap
ConcurrentSkipListMap
代码案例
package com.rumenz.task;import java.util.Map;
import java.util.concurrent.*;
//线程安全
public class ConcurrentSkipListMapExample {
public static Integer clientTotal=5000;
public static Integer threadTotal=200;
private static Map<Integer,Integer> map=new ConcurrentSkipListMap<>();
public static void main(String[] args) throws Exception{
ExecutorService executorService = Executors.newCachedThreadPool();
final Semaphore semaphore=new Semaphore(threadTotal);
final CountDownLatch countDownLatch=new CountDownLatch(clientTotal);
for (int i = 0; i < clientTotal; i++) {
final Integer j=i;
executorService.execute(()->{
try{
semaphore.acquire();
update(j);
semaphore.release();
}catch (Exception e){
e.printStackTrace();
}
countDownLatch.countDown();
});
}
countDownLatch.await();
executorService.shutdown();
System.out.println("size:"+map.size());
}
private static void update(Integer j) {
map.put(j, j);
}
}
//size:5000
ConcurrentHashMap
与ConcurrentSkipListMap
的对比
ConcurrentHashMap
比ConcurrentSkipListMap
性能要好一些。ConcurrentSkipListMap
的key
是有序的,ConcurrentHashMap
做不到。ConcurrentSkipListMap
支持高并发,它的时间复杂度是log(N)
,和线程数无关,也就是说任务一定的情况下,并发的线程越多,ConcurrentSkipListMap
的优势就越能体现出来。
关注微信公众号:【入门小站】解锁更多知识点
以上是 【Java】Java并发容器J.U.C 的全部内容, 来源链接: utcz.com/a/96437.html