java中CopyOnWrite的应用场景有哪些?缺点有哪些?

上次已经为大家介绍过java中CopyOnWrite容器是什么的主要内容了。今天再为大家介绍一些与之相关的内容,也就是java中CopyOnWrite的应用场景有哪些以及缺点有哪些?一起来看看吧。

首先,我们需要知道的是,CopyOnWrite并发容器用于读多写少的并发场景。比如白名单,黑名单,商品类目的访问和更新场景,假如我们有一个搜索网站,用户在这个网站的搜索框中,输入关键字搜索内容,但是某些关键字不允许被搜索。

这些不能被搜索的关键字会被放在一个黑名单当中,黑名单每天晚上更新一次。当用户搜索时,会检查当前关键字在不在黑名单当中,如果在,则提示不能搜索。实现代码如下:

package com.ifeve.book;
import java.util.Map;
import com.ifeve.book.forkjoin.CopyOnWriteMap;
/** 
 * 黑名单服务 
 * 
 * @author fangtengfei 
 * 
 */
public class BlackListServiceImpl
{
    private static CopyOnWriteMap < String, Boolean > blackListMap = new CopyOnWriteMap < String, Boolean > (
        1000);
    public static boolean isBlackList(String id)
    {
        return blackListMap.get(id) == null ? false : true;
    }
    public static void addBlackList(String id)
    {
        blackListMap.put(id, Boolean.TRUE);
    }
    /** 
     * 批量添加黑名单 
     * 
     * @param ids 
     */
    public static void addBlackList(Map < String, Boolean > ids)
    {
        blackListMap.putAll(ids);
    }
}

需要注意的是:

1.减少扩容开销。根据实际需要,初始化CopyOnWriteMap的大小,避免写时CopyOnWriteMap扩容的开销。

2.使用批量添加。因为每次添加,容器每次都会进行复制,所以减少添加次数,可以减少容器的复制次数。如使用上面代码里的addBlackList方法。

然后说一下,CopyOnWrite的缺点

1.内存占用问题

因为CopyOnWrite的写时复制机制,所以在进行写操作的时候,内存里会同时驻扎两个对象的内存,旧的对象和新写入的对象(注意:在复制的时候只是复制容器里的引用,只是在写的时候会创建新对象添加到新容器里,而旧容器的对象还在使用,所以有两份对象内存)。

如果这些对象占用的内存比较大,比如说200M左右,那么再写入100M数据进去,内存就会占用300M,那么这个时候很有可能造成频繁的Yong GC和Full GC。之前我们系统中使用了一个服务由于每晚使用CopyOnWrite机制更新大对象,造成了每晚15秒的Full GC,应用响应时间也随之变长。

针对内存占用问题,可以通过压缩容器中的元素的方法来减少大对象的内存消耗,比如,如果元素全是10进制的数字,可以考虑把它压缩成36进制或64进制。或者不使用CopyOnWrite容器,而使用其他的并发容器,如ConcurrentHashMap。

2.数据一致性问题

CopyOnWrite容器只能保证数据的最终一致性,不能保证数据的实时一致性。所以如果你希望写入的的数据,马上能读到,请不要使用CopyOnWrite容器。

以上就是关于java中CopyOnWrite的应用场景有哪些以及缺点有哪些的主要内容了。解析的也比较简单易懂。如果你对java知识感兴趣,想要了解更多java基础知识以及常见问题,敬请关注奇Q 工具网。

推荐阅读:

java spring依赖注入有哪些缺点?升级版新特征是什么?

java中二分查找的长度是多少?它有哪些优缺点?

java Lambda表达式优缺点,函数式接口详细介绍