模式"/>
并发编码模式
解决线程处理共享数据除了之前的线程变量(ThreadLocal)和不可变(Immatable)模式外,还有一个方式就是CopyOnWrite模式(也叫COW ),但是有自己的适用场景。针对该模式 java juc提供了 CopyOnWriteArrayList、CopyOnWriteArraySet(底层使用CopyOnWriteArrayList保证去重实现)。
一、使用场景
1、读多写少
2、数据量比较小
3、对数据的一致性要求不是非常的高
二、原理
读数据:直接进行读取
写数据:将原数据进行Copy,再进行修改(所以需要一致性要求数据量比较小),最后将原对象的属性指向修改后的数组地址;
所以当并行修改和查询时,可能查询到旧数据(所以需要一致性要求不是特别高)
三、CopyOnWriteArrayList源码(其他方法与add类似)
public class CopyOnWriteArrayList<E> implements List<E>, RandomAccess, Cloneable, Serializable {private static final long serialVersionUID = 8673264195747942595L;final transient ReentrantLock lock = new ReentrantLock();private transient volatile Object[] array;private static final Unsafe UNSAFE;private static final long lockOffset;
}
public boolean add(E var1) {// 有修改时,先加锁(所以最好读多写少场景)ReentrantLock var2 = this.lock;var2.lock();boolean var6;try {Object[] var3 = this.getArray();int var4 = var3.length;// 先Copy再修改Object[] var5 = Arrays.copyOf(var3, var4 + 1);var5[var4] = var1;// 最后设置新值this.setArray(var5);var6 = true;} finally {var2.unlock();}return var6;
}
四、使用场景实例
比如微服务去定时去获取服务请求列表信息时,如:Ribbon等服务列表,就比较适用该场景。数据一致性要求不是很高,数据量比较小,读多写少。
demo数据结构如: ConcurrentHashMap<String, CopyOnWriteArraySet<Router>>
//路由信息
public final class Router{private final String ip;private final Integer port;private final String iface;//构造函数public Router(String ip, Integer port, String iface){this.ip = ip;this.port = port;this.iface = iface;}//重写equals方法public boolean equals(Object obj){if (obj instanceof Router) {Router r = (Router)obj;return iface.equals(r.iface) &&ip.equals(r.ip) &&port.equals(r.port);}return false;}public int hashCode() {//省略hashCode相关代码}
}
//路由表信息
public class RouterTable {//Key:接口名//Value:路由集合ConcurrentHashMap<String, CopyOnWriteArraySet<Router>> rt = new ConcurrentHashMap<>();//根据接口名获取路由表public Set<Router> get(String iface){return rt.get(iface);}//删除路由public void remove(Router router) {Set<Router> set=rt.get(router.iface);if (set != null) {set.remove(router);}}//增加路由public void add(Router router) {Set<Router> set = rtputeIfAbsent(route.iface, r -> new CopyOnWriteArraySet<>());set.add(router);}
}
更多推荐
并发编码模式
发布评论