Java多线程-缓存框架

本文探讨了从简单HashMap缓存到高级解决方案,如装饰者模式、ConcurrentHashMap和Future,如何解决并发安全、重复计算及异常处理等问题。通过实例展示了缓存优化和线程同步的最佳实践。
摘要由CSDN通过智能技术生成

缓存框架

1、使用HashMap实现一个缓存

/**
 * @Classname ImocCache1
 * @Description 最简单的缓存形式,HashMap
 * @Date 2021/5/24 22:44
 * @Created by WangXiong
 */
public class ImocCache1 {

    private HashMap<String, Integer> cache = new HashMap<>();

    public Integer computer(String userId) throws InterruptedException {
        Integer result = cache.get(userId);
        //先检查hashmap中是否有这个缓存
        if (result == null){
            //如果缓存中找不到,需要重新计算一下结果,然后保存到cache中
            result = doCompute(userId);
            cache.put(userId, result);
        }
        return result;
    }

    public Integer doCompute(String userId) throws InterruptedException {
        TimeUnit.SECONDS.sleep(5);
        return new Integer(userId);
    }

    public static void main(String[] args) throws InterruptedException {
        ImocCache1 imocCache1 = new ImocCache1();
        System.out.println("开始计算了");
        Integer result = imocCache1.computer("13");
        System.out.println("第一次计算的结果"+result);
        result = imocCache1.computer("13");
        System.out.println("第二次计算的结果"+result);

    }
}

多个线程同时进来,会有并发安全问题,且代码耦合

2、用装饰者模式来解决解耦的问题

/**
 * @Classname Computable
 * @Description 有一个计算函数computer,用来代表耗时计算,每个计算器都要实现这个接口,这样就
 * 可以无侵入实现缓存的功能
 * @Date 2021/5/24 22:56
 * @Created by WangXiong
 */
public interface Computable<A, V> {
     V computer(A arg) throws Exception;
}
/**
 * @Classname ExpensiveFuntion
 * @Description 耗时计算的实现类,实现了Computable接口,但是本身不具备缓存能力,不需要考虑
 * 缓存的事情
 * @Date 2021/5/24 22:58
 * @Created by WangXiong
 */
public class ExpensiveFunction implements Computable<String, Integer>{

    @Override
    public Integer computer(String arg) throws Exception {
        Thread.sleep(5000);
        return Integer.valueOf(arg);
    }
}
/**
 * @Classname ImocCache1
 * @Description 用装饰者模式,给计算器自动添加缓存功能
 * @Date 2021/5/24 22:44
 * @Created by WangXiong
 */
public class ImocCache2<A, V> implements Computable<A, V> {

    private HashMap<A, V> cache = new HashMap<>();

    private final Computable<A, V> c;

    public ImocCache2(Computable<A, V> c) {
        this.c = c;
    }

    @Override
    public V computer(A arg) throws Exception {
        System.out.println("进入缓存机制");
        V result = cache.get(arg);
        if (result == null){
            result =  c.computer(arg);
            cache.put(arg, result);
        }
        return result;
    }

    public static void main(String[] args) throws Exception {
        ImocCache2<String, Integer> exImocCache2 = new ImocCache2<>(new ExpensiveFunction());
        Integer result = exImocCache2.computer("666");
        System.out.println("第一次计算结果"+result);
        result = exImocCache2.computer("666");
        System.out.println("第二次计算结果"+result);
    }
}

 3、多线程中会有线程安全问题

使用synchronize来处理线程安全问题

/**
 * @Classname ImocCache1
 * @Description 演示synchronized的问题,导致性能差,没有办法多个线程同时访问缓存
 * @Date 2021/5/24 22:44
 * @Created by WangXiong
 */
public class ImocCache3<A, V> implements Computable<A, V> {

    private HashMap<A, V> cache = new HashMap<>();

    private final Computable<A, V> c;

    public ImocCache3(Computable<A, V> c) {
        this.c = c;
    }

    @Override
    //由于加上了synchronized,这个方法同时只能一个线程访问,效率低下
    public synchronized V computer(A arg) throws Exception {
        System.out.println("进入缓存机制1");
        V result = cache.get(arg);
        if (result == null){
            result =  c.computer(arg);
            cache.put(arg, result);
        }
        return result;
    }

    public static void main(String[] args) throws Exception {
        ImocCache3<String, Integer> exImocCache2 = new ImocCache3<>(new ExpensiveFunction());
        new Thread(new Runnable() {
            @Override
            public void run() {
                try {
                    Integer result = exImocCache2.computer("666");
                    System.out.println("第一个线程end"+result);
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        }).start();
        new Thread(new Runnable() {
            @Override
            public void run() {
                try {
                    Integer result = exImocCache2.computer("666");
                    System.out.println("第二个线程end"+result);
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        }).start();
        new Thread(new Runnable() {
            @Override
            public void run() {
                try {
                    Integer result = exImocCache2.computer("777");
                    System.out.println("第三个线程end"+result);
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        }).start();
    }
}

4、降低synchronize粒度

将synchronize的粒度降低,让线程性能提高,但是这样依旧会有性能问题。

/**
 * @Classname ImocCache1
 * @Description 使用synchronized缩小粒度,提高性能,但是依旧是线程不安全的
 * @Date 2021/5/24 22:44
 * @Created by WangXiong
 */
public class ImocCache4<A, V> implements Computable<A, V> {

    private HashMap<A, V> cache = new HashMap<>();

    private final Computable<A, V> c;

    public ImocCache4(Computable<A, V> c) {
        this.c = c;
    }

    @Override
    public V computer(A arg) throws Exception {
        System.out.println("进入缓存机制1");
        //读的时候也会有线程安全的问题
        V result = cache.get(arg);
        if (result == null){
            result =  c.computer(arg);
            synchronized (this) {
                cache.put(arg, result);
            }
        }
        return result;
    }

    public static void main(String[] args) throws Exception {
        ImocCache4<String, Integer> exImocCache2 = new ImocCache4<>(new ExpensiveFunction());
        new Thread(new Runnable() {
            @Override
            public void run() {
                try {
                    Integer result = exImocCache2.computer("666");
                    System.out.println("第一个线程end"+result);
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        }).start();
        new Thread(new Runnable() {
            @Override
            public void run() {
                try {
                    Integer result = exImocCache2.computer("666");
                    System.out.println("第二个线程end"+result);
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        }).start();
        new Thread(new Runnable() {
            @Override
            public void run() {
                try {
                    Integer result = exImocCache2.computer("777");
                    System.out.println("第三个线程end"+result);
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        }).start();
    }
}

5.使用线程安全的HashMap

/**
 * @Classname ImocCache1
 * @Description 使用ConcurrentHashMap优化缓存
 * @Date 2021/5/24 22:44
 * @Created by WangXiong
 */
public class ImocCache5<A, V> implements Computable<A, V> {

    private ConcurrentHashMap<A, V> cache = new ConcurrentHashMap<>();

    private final Computable<A, V> c;

    public ImocCache5(Computable<A, V> c) {
        this.c = c;
    }

    @Override
    public V computer(A arg) throws Exception {
        System.out.println("进入缓存机制1");
        //读的时候也会有线程安全的问题
        V result = cache.get(arg);
        if (result == null){
            result =  c.computer(arg);
            cache.put(arg, result);
        }
        return result;
    }

    public static void main(String[] args) throws Exception {
        ImocCache5<String, Integer> exImocCache2 = new ImocCache5<>(new ExpensiveFunction());
        new Thread(new Runnable() {
            @Override
            public void run() {
                try {
                    Integer result = exImocCache2.computer("666");
                    System.out.println("第一个线程end"+result);
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        }).start();
        new Thread(new Runnable() {
            @Override
            public void run() {
                try {
                    Integer result = exImocCache2.computer("666");
                    System.out.println("第二个线程end"+result);
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        }).start();
        new Thread(new Runnable() {
            @Override
            public void run() {
                try {
                    Integer result = exImocCache2.computer("777");
                    System.out.println("第三个线程end"+result);
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        }).start();
    }
}

6、解决缓存值重复计算的问题

演示值计算多遍的问题

/**
 * @Classname ImocCache1
 * @Description 使用ConcurrentHashMap优化缓存,还是会有问题,会有计算多遍的问题
 * @Date 2021/5/24 22:44
 * @Created by WangXiong
 */
public class ImocCache6<A, V> implements Computable<A, V> {

    private ConcurrentHashMap<A, V> cache = new ConcurrentHashMap<>();

    private final Computable<A, V> c;

    public ImocCache6(Computable<A, V> c) {
        this.c = c;
    }

    @Override
    public V computer(A arg) throws Exception {
        System.out.println("进入缓存机制1");
        V result = cache.get(arg);
        if (result == null){
            //计算是耗时的,第二个线程过来还没有算好,也会去进行计算
            result =  c.computer(arg);
            cache.put(arg, result);
        }
        return result;
    }

    public static void main(String[] args) throws Exception {
        ImocCache6<String, Integer> exImocCache2 = new ImocCache6<>(new ExpensiveFunction());
        new Thread(new Runnable() {
            @Override
            public void run() {
                try {
                    Integer result = exImocCache2.computer("666");
                    System.out.println("第一个线程end"+result);
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        }).start();
        new Thread(new Runnable() {
            @Override
            public void run() {
                try {
                    Integer result = exImocCache2.computer("666");
                    System.out.println("第二个线程end"+result);
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        }).start();
        new Thread(new Runnable() {
            @Override
            public void run() {
                try {
                    Integer result = exImocCache2.computer("777");
                    System.out.println("第三个线程end"+result);
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        }).start();
    }
}

效果

使用Future来解决重复计算的问题

/**
 * @Classname ImocCache1
 * @Description 使用Future来解决重复计算的问题
 * @Date 2021/5/24 22:44
 * @Created by WangXiong
 */
public class ImocCache7<A, V> implements Computable<A, V> {

    private final Map<A, Future<V>> cache = new ConcurrentHashMap<>();

    private final Computable<A, V> c;

    public ImocCache7(Computable<A, V> c) {
        this.c = c;
    }

    @Override
    public V computer(A arg) throws Exception {
        Future<V> f = cache.get(arg);
        if (f == null) {
            Callable<V> callable = new Callable<V>() {

                @Override
                public V call() throws Exception {
                    return c.computer(arg);
                }
            };
            FutureTask<V> ft = new FutureTask<>(callable);
            f = ft;
            cache.put(arg, ft);
            System.out.println("从FutureTask调用了计算函数");
            ft.run();
        }

        return f.get();
    }

    public static void main(String[] args) throws Exception {
        ImocCache7<String, Integer> exImocCache2 = new ImocCache7<>(new ExpensiveFunction());
        new Thread(new Runnable() {
            @Override
            public void run() {
                try {
                    Integer result = exImocCache2.computer("666");
                    System.out.println("第一个线程end"+result);
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        }).start();
        new Thread(new Runnable() {
            @Override
            public void run() {
                try {
                    Integer result = exImocCache2.computer("777");
                    System.out.println("第三个线程end"+result);
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        }).start();
        new Thread(new Runnable() {
            @Override
            public void run() {
                try {
                    Integer result = exImocCache2.computer("666");
                    System.out.println("第二个线程end"+result);
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        }).start();
    }
}

效果

我们调整下线程之间的顺序,依旧会出现重复计算的问题。因为在第一个线程还没有put进去的时候,第二个线程就去get了,这个时候也会认为是没有计算的,一旦进入到if中,就一定回去进行计算。可以使用ConcurrentHashMap提供的方法来解决这个问题,因为ConcurrentHashMap的方法都是线程安全的,所以不用考虑线程安全问题

/**
 * @Classname ImocCache1
 * @Description 使用Future依旧会出现一定几率的重复计算,
 * 使用ConcurrentHashMap的提供的方法putIfAbsent()进行避免
 * @Date 2021/5/24 22:44
 * @Created by WangXiong
 */
public class ImocCache8<A, V> implements Computable<A, V> {

    private final Map<A, Future<V>> cache = new ConcurrentHashMap<>();

    private final Computable<A, V> c;

    public ImocCache8(Computable<A, V> c) {
        this.c = c;
    }

    @Override
    public V computer(A arg) throws Exception {
        Future<V> f = cache.get(arg);
        if (f == null) {
            Callable<V> callable = new Callable<V>() {

                @Override
                public V call() throws Exception {
                    return c.computer(arg);
                }
            };
            FutureTask<V> ft = new FutureTask<>(callable);
            //putIfAbsentr如果存在arg的key的数据,就不会进行put操作,如果为空,会返回null
            f = cache.putIfAbsent(arg, ft);
            if (f == null) {
                f = ft;
                System.out.println("从FutureTask调用了计算函数");
                ft.run();
            }

        }

        return f.get();
    }

    public static void main(String[] args) throws Exception {
        ImocCache8<String, Integer> exImocCache2 = new ImocCache8<>(new ExpensiveFunction());
        new Thread(new Runnable() {
            @Override
            public void run() {
                try {
                    Integer result = exImocCache2.computer("666");
                    System.out.println("第一个线程end"+result);
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        }).start();
        new Thread(new Runnable() {
            @Override
            public void run() {
                try {
                    Integer result = exImocCache2.computer("666");
                    System.out.println("第二个线程end"+result);
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        }).start();
        new Thread(new Runnable() {
            @Override
            public void run() {
                try {
                    Integer result = exImocCache2.computer("777");
                    System.out.println("第三个线程end"+result);
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        }).start();
    }
}

7、给缓存类增加异常处理的能力

/**
 * @Classname ImocCache1
 * @Description 给缓存类增加异常处理的能力
 * @Date 2021/5/24 22:44
 * @Created by WangXiong
 */
public class ImocCache9<A, V> implements Computable<A, V> {

    private final Map<A, Future<V>> cache = new ConcurrentHashMap<>();

    private final Computable<A, V> c;

    public ImocCache9(Computable<A, V> c) {
        this.c = c;
    }

    @Override
    public V computer(A arg) throws InterruptedException, ExecutionException {
        while (true) {
            Future<V> f = cache.get(arg);
            if (f == null) {
                Callable<V> callable = new Callable<V>() {

                    @Override
                    public V call() throws Exception {
                        return c.computer(arg);
                    }
                };
                FutureTask<V> ft = new FutureTask<>(callable);
                //putIfAbsentr如果存在arg的key的数据,就不会进行put操作,如果为空,会返回null
                f = cache.putIfAbsent(arg, ft);
                if (f == null) {
                    f = ft;
                    System.out.println("从FutureTask调用了计算函数");
                    ft.run();
                }

            }
            try {
                return f.get();
            } catch (CancellationException e) {
                System.out.println("被取消了");
                cache.remove(arg);
                throw e;
            } catch (InterruptedException e) {
                System.out.println("被中断了");
                cache.remove(arg);
                throw e;
            } catch (ExecutionException e) {
                System.out.println("计算错误,需要重试");
                //异常了,一定要删除缓存数据,不然会有污染数据,导致一直重试
                cache.remove(arg);
            }
        }

    }

    public static void main(String[] args) throws Exception {
        ImocCache9<String, Integer> exImocCache2 = new ImocCache9<>(new MayFail());
        new Thread(new Runnable() {
            @Override
            public void run() {
                try {
                    Integer result = exImocCache2.computer("666");
                    System.out.println("第一个线程end"+result);
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        }).start();
        new Thread(new Runnable() {
            @Override
            public void run() {
                try {
                    Integer result = exImocCache2.computer("666");
                    System.out.println("第二个线程end"+result);
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        }).start();
        new Thread(new Runnable() {
            @Override
            public void run() {
                try {
                    Integer result = exImocCache2.computer("777");
                    System.out.println("第三个线程end"+result);
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        }).start();
        // Thread.sleep(3000);
        // Future<Integer> future = exImocCache2.cache.get("666");
        // future.cancel(false);
    }
}

8、 给缓存类增加过期功能

/**
 * @Classname ImocCache1
 * @Description 给缓存类增加缓存过期的功能
 * @Date 2021/5/24 22:44
 * @Created by WangXiong
 */
public class ImocCache10<A, V> implements Computable<A, V> {

    private final Map<A, Future<V>> cache = new ConcurrentHashMap<>();

    private final Computable<A, V> c;

    public ImocCache10(Computable<A, V> c) {
        this.c = c;
    }

    @Override
    public V computer(A arg) throws InterruptedException, ExecutionException {
        while (true) {
            Future<V> f = cache.get(arg);
            if (f == null) {
                Callable<V> callable = new Callable<V>() {

                    @Override
                    public V call() throws Exception {
                        return c.computer(arg);
                    }
                };
                FutureTask<V> ft = new FutureTask<>(callable);
                //putIfAbsentr如果存在arg的key的数据,就不会进行put操作,如果为空,会返回null
                f = cache.putIfAbsent(arg, ft);
                if (f == null) {
                    f = ft;
                    System.out.println("从FutureTask调用了计算函数");
                    ft.run();
                }

            }
            try {
                return f.get();
            } catch (CancellationException e) {
                System.out.println("被取消了");
                cache.remove(arg);
                throw e;
            } catch (InterruptedException e) {
                System.out.println("被中断了");
                cache.remove(arg);
                throw e;
            } catch (ExecutionException e) {
                System.out.println("计算错误,需要重试");
                //异常了,一定要删除缓存数据,不然会有污染数据,导致一直重试
                cache.remove(arg);
            }
        }

    }

    public final ScheduledExecutorService service = Executors.newScheduledThreadPool(5);
    //为避免缓存雪崩,写一个产生随机值的缓存时间的方法
    public V computerRandomExpire(A arg) throws ExecutionException, InterruptedException {
        long randomExpire = (long) (Math.random() * 10000);
        System.out.println("computerRandomExpire设置的缓存时间:"+randomExpire);
        return computer(arg, randomExpire);
    }
    public V computer(A arg, long expire) throws ExecutionException, InterruptedException {
        //设置相同的缓存失效时间,会造成缓存雪崩
        service.schedule(new Runnable() {
            @Override
            public void run() {
                expire(arg);
            }
        }, expire, TimeUnit.MILLISECONDS);
        return computer(arg);
    }

    public synchronized void expire(A key){
        Future<V> future = cache.get(key);
        if (future != null) {
            if (!future.isDone()){
                System.out.println("Future任务被取消");
                future.cancel(true);
            }
            System.out.println("过期时间到,缓存被清除");
            cache.remove(key);
        }
    }

    public static void main(String[] args) throws Exception {
        ImocCache10<String, Integer> exImocCache2 = new ImocCache10<>(new MayFail());
        new Thread(new Runnable() {
            @Override
            public void run() {
                try {
                    Integer result = exImocCache2.computerRandomExpire("666");
                    System.out.println("第一个线程end"+result);
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        }).start();
        new Thread(new Runnable() {
            @Override
            public void run() {
                try {
                    Integer result = exImocCache2.computer("666");
                    System.out.println("第二个线程end"+result);
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        }).start();
        new Thread(new Runnable() {
            @Override
            public void run() {
                try {
                    Integer result = exImocCache2.computer("777");
                    System.out.println("第三个线程end"+result);
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        }).start();
        // Thread.sleep(3000);
        // Future<Integer> future = exImocCache2.cache.get("666");
        // future.cancel(false);

        Thread.sleep(7000l);
        new Thread(new Runnable() {
            @Override
            public void run() {
                try {
                    Integer result = exImocCache2.computer("666");
                    System.out.println("第四个线程end"+result);
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        }).start();
    }
}

9、 测试缓存性能

/**
 * @Classname ImocCache1
 * @Description 测试环境耗时
 * @Date 2021/5/24 22:44
 * @Created by WangXiong
 */
public class ImocCache11<A, V> {

    static ImocCache10<String, Integer> imocCache10 = new ImocCache10<>(new ExpensiveFunction());
    public static void main(String[] args) {
        ExecutorService service = Executors.newFixedThreadPool(3000);
        long start = System.currentTimeMillis();
        for (int i = 0; i < 3000; i++) {
            service.submit(()->{
                try {
                    imocCache10.computer("666");
                } catch (InterruptedException e) {
                    e.printStackTrace();
                } catch (ExecutionException e) {
                    e.printStackTrace();
                }
            });
        }
        service.shutdown();
        while (!service.isTerminated()){

        }
        long end = System.currentTimeMillis();
        System.out.println("耗时:"+(end-start));
    }
}

借助CountDownLatch来实现压测的效果

/**
 * @Classname ImocCache1
 * @Description 测试环境耗时
 * @Date 2021/5/24 22:44
 * @Created by WangXiong
 */
public class ImocCache11<A, V> {

    static ImocCache10<String, Integer> imocCache10 = new ImocCache10<>(new ExpensiveFunction());
    public static final CountDownLatch countDownLatch = new CountDownLatch(1);
    public static void main(String[] args) throws InterruptedException {
        ExecutorService service = Executors.newFixedThreadPool(3000);
        long start = System.currentTimeMillis();
        for (int i = 0; i < 3000; i++) {
            service.submit(()->{
                try {
                    System.out.println(Thread.currentThread().getName() + "开始等待");
                    countDownLatch.await();
                    Integer result = imocCache10.computer("666");
                    System.out.println(Thread.currentThread().getName() + "结束等待");
                    System.out.println(result);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                } catch (ExecutionException e) {
                    e.printStackTrace();
                }
            });
        }

        Thread.sleep(5000);
        countDownLatch.countDown();
        service.shutdown();

    }
}

每个线程都打印自己的时间,用ThreadLocal来实现

/**
 * @Classname ImocCache1
 * @Description 测试环境耗时,使用ThreadLocal线程来存储变量
 * @Date 2021/5/24 22:44
 * @Created by WangXiong
 */
public class ImocCache11<A, V> {

    static ImocCache10<String, Integer> imocCache10 = new ImocCache10<>(new ExpensiveFunction());
    public static final CountDownLatch countDownLatch = new CountDownLatch(1);
    public static void main(String[] args) throws InterruptedException {
        ExecutorService service = Executors.newFixedThreadPool(3000);
        long start = System.currentTimeMillis();
        for (int i = 0; i < 3000; i++) {
            service.submit(()->{
                try {
                    System.out.println(Thread.currentThread().getName() + "开始等待");
                    countDownLatch.await();
                    SimpleDateFormat dateFormat = ThreadSafeFormatter.dft.get();
                    String format = dateFormat.format(new Date());
                    Integer result = imocCache10.computer("666");
                    System.out.println(Thread.currentThread().getName() + "    " + format + "被放行");
                    // System.out.println(result);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                } catch (ExecutionException e) {
                    e.printStackTrace();
                }
            });
        }

        Thread.sleep(5000);
        countDownLatch.countDown();
        service.shutdown();

    }
}

class ThreadSafeFormatter {
    public static ThreadLocal<SimpleDateFormat> dft = new ThreadLocal<SimpleDateFormat>(){
        @Override
        protected SimpleDateFormat initialValue() {
            return new SimpleDateFormat("mm:ss");
        }

        @Override
        public SimpleDateFormat get() {
            return super.get();
        }
    };
}

10、总结

用HashMap作为缓存进行迭代

用synchronize来解决线程安全问题,但是会影响性能

用装饰者模式来解决代码侵入的问题,重复的代码可以进行复用

将类锁的synchronize换为粒度更小的代码块,但是依旧会有线程安全问题

使用ConcurrentHashMap线程安全的map来解决,但是在一定的情况下依旧是线程不安全,并且会有重复计算的问题

使用Future来解决重复计算的问题,并且用ConcurrentHashMap提供的线程安全的方法来解决上面一定情况下线程不安全的情况

增加异常处理,对取消和中断做不同的处理,对计算错误可以进行重试(需要在计算失败的时候,进行缓存移除,不然会有缓存污染问题)

需要增加缓存过期问题,对缓存时间设置的不一致,设置随机值 ,避免雪崩

利用CountDownLatch来进行压测

使用ThreadLocal来处理打印时间的问题

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值