`
nannan408
  • 浏览: 1783326 次
  • 性别: Icon_minigender_1
  • 来自: 深圳
社区版块
存档分类
最新评论

架构师之jdk8-----------------ConcurrentHashMap快速构建本地缓存和单例模式

 
阅读更多
1.前言。
   本地缓存和复杂的单例写起来不仅效率低下,而且费时。ConcurrentHashMap+computeIfAbsent使得可以直接快速构建。
2.例子.
 
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;
 
public class Main {
    static Map<Integer, Integer> cache = new ConcurrentHashMap<>();
 
    public static void main(String[] args) throws InterruptedException {
        cache.put(0, 0);
        cache.put(1, 1);
        // 普通方式
        System.out.println("Fibonacci(7) = " + fibonacci(7));
        // 采用java7的同步线程方式及java8的本地缓存的方式
        System.out.println("FibonacciJava8(7) = " + fibonacciJava8(7));
        System.out.println("FibonacciJava7(7) = " + fibonacciJava7(7));
 
        // 构建多值Map样例代码
        Map<String, HashSet<String>> map1 = new HashMap<>();
        map1.computeIfAbsent("fruits", k -> genValue(k)).add("apple");
        map1.computeIfAbsent("fruits", k -> genValue(k)).add("orange");
        map1.computeIfAbsent("fruits", k -> genValue(k)).add("pear");
        map1.computeIfAbsent("fruits", k -> genValue(k)).add("banana");
        map1.computeIfAbsent("fruits", k -> genValue(k)).add("water");
        System.out.println(map1);
 
        //测试多线程并发处理,是否同步操作
        Map<String, String> map2 = new ConcurrentHashMap<>();
        ExecutorService exec = Executors.newCachedThreadPool();
        for (int i = 0; i < 5; i++) {
            exec.execute(() -> {
                map2.computeIfAbsent("name", k -> genValue2(k));
                map2.computeIfAbsent("addr", k -> genValue2(k));
                map2.computeIfAbsent("email", k -> genValue2(k));
                map2.computeIfAbsent("mobile", k -> genValue2(k));
            });
        }
        exec.shutdown();
        exec.awaitTermination(1, TimeUnit.SECONDS);
        System.out.println(map2);
    }
 
    static HashSet<String> genValue(String str) {
        return new HashSet<String>();
    }
 
    static String genValue2(String str) {
        System.out.println("===");
        return str + "2";
    }
 
    /**
     * 普通的实现方式 普通方式使用大量的计算,存在性能问题. 并且计算量随着n的增加呈指数级增加,需要用到一些缓存策略,并且是线程安全的.
     *
     * @param n
     * @return
     */
    static int fibonacci(int n) {
        if (n == 0 || n == 1)
            return n;
 
        System.out.println("calculating Fibonacci(" + n + ")");
        return fibonacci(n - 2) + fibonacci(n - 1);
    }
 
    /**
     * 采用java8的本地缓存方式 如果缓存MAP中不存在指定key的值,会自动调用mappingFunction(key)计算key的value
     * 然后将key = value放入到缓存Map,java8会使用thread-safe的方式从cache中存取记录
     *
     * @param n
     * @return
     */
    static int fibonacciJava8(int n) {
        return cache.computeIfAbsent(n, (key) -> {
            System.out.println("calculating FibonacciJava8 " + n);
            return fibonacciJava8(n - 2) + fibonacciJava8(n - 1);
        });
    }
 
    /**
     * 在java7中的实现方式
     * 在java7中,通过synchronized进行线程同步,检查缓存是否存在key对应的值,如果不存在才进行计算并放入缓存中
     * 为了更好的性能,需要使用 double-checked locking,那样代码会更复杂
     *
     * @param n
     * @return
     */
    static int fibonacciJava7(int n) {
        if (n == 0 || n == 1)
            return n;
 
        Integer result = cache.get(n);
 
        if (result == null) {
            synchronized (cache) {
                result = cache.get(n);
 
                if (result == null) {
                    System.out.println("calculating FibonacciJava7(" + n + ")");
                    result = fibonacciJava7(n - 2) + fibonacciJava7(n - 1);
                    cache.put(n, result);
                }
            }
        }
        return result;
    }
}


  运行结果:
 
calculating Fibonacci(7)
calculating Fibonacci(5)
calculating Fibonacci(3)
calculating Fibonacci(2)
calculating Fibonacci(4)
calculating Fibonacci(2)
calculating Fibonacci(3)
calculating Fibonacci(2)
calculating Fibonacci(6)
calculating Fibonacci(4)
calculating Fibonacci(2)
calculating Fibonacci(3)
calculating Fibonacci(2)
calculating Fibonacci(5)
calculating Fibonacci(3)
calculating Fibonacci(2)
calculating Fibonacci(4)
calculating Fibonacci(2)
calculating Fibonacci(3)
calculating Fibonacci(2)
Fibonacci(7) = 13
calculating FibonacciJava8 7
calculating FibonacciJava8 5
calculating FibonacciJava8 3
calculating FibonacciJava8 2
calculating FibonacciJava8 4
calculating FibonacciJava8 6
FibonacciJava8(7) = 13
FibonacciJava7(7) = 13
{fruits=[orange, banana, apple, pear, water]}
===
===
===
===
{name=name2, mobile=mobile2, addr=addr2, email=email2}


分享到:
评论
1 楼 bilimeng 2018-07-09  
求教,ConcurrentHashMap不是线程安全的么,为啥还要加锁?不是多此一举吗??

相关推荐

    java-jdk1.8-8u361-all-jdk-win-linux

    jdk-8u361-linux-aarch64.rpm jdk-8u361-linux-i586.rpm jdk-8u361-linux-i586.tar.gz jdk-8u361-linux-x64.rpm jdk-8u361-linux-x64.tar.gz jdk-8u361-windows-i586.exe jdk-8u361-windows-x64.exe 如果需要mac版本...

    jdk-8u131-windows-x64

    jdk-8u131-windows-x64jdk-8u131-windows-x64jdk-8u131-windows-x64jdk-8u131-windows-x64jdk-8u131-windows-x64jdk-8u131-windows-x64jdk-8u131-windows-x64jdk-8u131-windows-x64jdk-8u131-windows-x64jdk-8u131-...

    jackson-datatype-jdk8-2.13.1-API文档-中英对照版.zip

    赠送jar包:jackson-datatype-jdk8-2.13.1.jar; 赠送原API文档:jackson-datatype-jdk8-2.13.1-javadoc.jar; 赠送源代码:jackson-datatype-jdk8-2.13.1-sources.jar; 赠送Maven依赖信息文件:jackson-datatype-...

    开发工具 jdk-8u121-windows-i586

    开发工具 jdk-8u121-windows-i586开发工具 jdk-8u121-windows-i586开发工具 jdk-8u121-windows-i586开发工具 jdk-8u121-windows-i586开发工具 jdk-8u121-windows-i586开发工具 jdk-8u121-windows-i586开发工具 jdk-8...

    jdk-8u311-windows-x64.exe

    jdk-8u311-windows-x64.exe jdk-8u311-windows-x64.exe.zip jdk-8u311-windows-x64.exe jdk-8u311-windows-x64.exe.zip jdk-8u311-windows-x64.exe jdk-8u311-windows-x64.exe.zip jdk-8u311-windows-x64.exe jdk-8u...

    jdk-8u60-windows-i586-JDK1.8-32位

    jdk-8u60-windows-i586 jdk-8u60-windows-i586 jdk-8u60-windows-i586 jdk-8u60-windows-i586 jdk-8u60-windows-i586

    bcprov-jdk14-1.38-API文档-中文版.zip

    赠送jar包:bcprov-jdk14-1.38.jar; 赠送原API文档:bcprov-jdk14-1.38-javadoc.jar; 赠送源代码:bcprov-jdk14-1.38-sources.jar; 赠送Maven依赖信息文件:bcprov-jdk14-1.38.pom; 包含翻译后的API文档:bcprov...

    jdk8-jdk-8u121-linux-x64.tar.gz

    这个压缩包 "jdk8-jdk-8u121-linux-x64.tar.gz" 包含了适用于Linux 64位系统的JDK 8更新121版本。** JDK是Java SE(Standard Edition)的一部分,它提供了Java编程语言和Java平台的开发环境。这个版本号“8u121”指...

    UOS服务器版MIPS架构龙芯openjdk-8-jdk-mips.tar.gz

    标题中的“UOS服务器版MIPS架构龙芯openjdk-8-jdk-mips.tar.gz”指的是一款专为UOS(Unity Operating System)服务器版本设计的、基于MIPS架构的龙芯处理器优化的OpenJDK 8 JDK软件包。UOS是中国自主研发的操作系统...

    bcprov-jdk14-1.38-API文档-中英对照版.zip

    赠送jar包:bcprov-jdk14-1.38.jar; 赠送原API文档:bcprov-jdk14-1.38-javadoc.jar; 赠送源代码:bcprov-jdk14-1.38-sources.jar; 赠送Maven依赖信息文件:bcprov-jdk14-1.38.pom; 包含翻译后的API文档:bcprov...

    bcmail-jdk14-1.38-API文档-中文版.zip

    赠送jar包:bcmail-jdk14-1.38.jar; 赠送原API文档:bcmail-jdk14-1.38-javadoc.jar; 赠送源代码:bcmail-jdk14-1.38-sources.jar; 赠送Maven依赖信息文件:bcmail-jdk14-1.38.pom; 包含翻译后的API文档:bcmail...

    jdk-8u131-windows-i586

    8u131-windows-i586jdk-8u131-windows-i586jdk-8u131-windows-i586jdk-8u131-windows-i586jdk-8u131-windows-i586jdk-8u131-windows-i586jdk-8u131-windows-i586jdk-8u131-windows-i586jdk-8u131-windows-i586jdk-...

    bcprov-jdk16-143.jar和bcprov-jdk15-135.jar

    解决no such provider: BC 问题所需的JAR 在jdk中的jre\lib\security修改java.security文件, security.provider.6=com.sun.security.sasl.Provider 下面添加...bcprov-jdk16-143.jar提供加密,解密,生成密钥对等方法

    jdk-8u202-linux-arm64-vfp-hflt-demos.tar.gz

    标题中的"jdk-8u202-linux-arm64-vfp-hflt-demos.tar.gz"表明这是一个针对Linux ARM架构(具体为vfp-hflt变体)的Java Development Kit(JDK)版本8更新202的示例(demos)压缩包。这个压缩文件采用tar.gz格式,是...

    jackson-datatype-jdk8-2.11.4-API文档-中文版.zip

    赠送jar包:jackson-datatype-jdk8-2.11.4.jar; 赠送原API文档:jackson-datatype-jdk8-2.11.4-javadoc.jar; 赠送源代码:jackson-datatype-jdk8-2.11.4-sources.jar; 赠送Maven依赖信息文件:jackson-datatype-...

    jdk-8u221-64bit.zip jdk-8版本安装包

    jdk-8版本安装包、 jdk-8版本安装包、 jdk-8版本安装包 jdk-8版本安装包、 jdk-8版本安装包、 jdk-8版本安装包 jdk-8版本安装包、 jdk-8版本安装包、 jdk-8版本安装包 jdk-8版本安装包、 jdk-8版本安装包、 jdk-8...

    jdk-7u80-windows-x64安装包

    jdk-7u80-windows-x64安装包 jdk-7u80-windows-x64安装包 jdk-7u80-windows-x64安装包 jdk-7u80-windows-x64安装包 jdk-7u80-windows-x64安装包 jdk-7u80-windows-x64安装包 jdk-7u80-windows-x64安装包 jdk-7u80-...

    bcprov-jdk16-146.jar和bcprov-jdk15-146.jar

    标题中的"bcprov-jdk16-146.jar"和"bcprov-jdk15-146.jar"是两个版本的Bouncy Castle提供者的Java档案(JAR)文件,用于加密和数字签名功能。Bouncy Castle是一个开源的Java加密库,它扩展了Java Cryptography ...

    arm架构下jdk-8u391-linux-aarch64.tar

    1. **下载JDK**: 首先,你需要从Oracle官方网站或者OpenJDK的源获取适用于ARM架构的JDK 8u391 Linux版的tar归档文件,即"jdk-8u391-linux-aarch64.tar"。 2. **解压JDK**: 使用`tar`命令解压缩下载的文件。例如: ...

    java-jdk1.8-jdk-8u192-windows-x64.zip

    标题中的"java-jdk1.8-jdk-8u192-windows-x64.zip"表明这是一个压缩包,内含64位的Java JDK 1.8u192版本,适用于Windows操作系统。这种格式的文件通常用于方便下载和传输大文件,用户需要先将其解压缩才能进行后续...

Global site tag (gtag.js) - Google Analytics