qiangchen1990 2019-03-07 17:02 采纳率: 0%
浏览 568
已采纳

线程从concurrentMap读取到指定key的值时不向集合写数据,下面的代码存在多个线程写数据

废话不多讲,直接贴代码:

 @Test
    public void test02() {
        try {
            log.debug("开始测试");
            ConcurrentMap<String, String> map = CacheBuilder.newBuilder()
                    .initialCapacity(10)
                    .expireAfterAccess(1, TimeUnit.HOURS)
                    .<String, String>build()
                    .asMap();

            CountDownLatch testMainCountDownLatch = new CountDownLatch(1);

            int count = 100;
            ExecutorService executorService = Executors.newFixedThreadPool(count);
            CountDownLatch countDownLatch = new CountDownLatch(count);
            for (int i = 0; i < count; i++) {
                executorService.submit(new Runnable() {
                    @Override
                    public void run() {
                        try {
                            log.debug("{}线程开始了", Thread.currentThread().getName());
                            Thread.sleep(1000);
                            countDownLatch.await();
                            if (StringUtils.isBlank(map.get("hello"))) {
                                log.debug("{}线程没有读取到值,开始写值", Thread.currentThread().getName());
                                map.put("hello", Thread.currentThread().getName());
                            } else {
                                log.debug("{}线程读取到值:{}", Thread.currentThread().getName(), map.get("hello"));
                            }
                        } catch (InterruptedException e) {
                            log.error(ExceptionUtils.getStackTrace(e));
                        }
                    }
                });
                countDownLatch.countDown();
            }


            testMainCountDownLatch.await();
        } catch (InterruptedException e) {
            log.error(ExceptionUtils.getStackTrace(e));
        }

    }

输出存在多个线程向concurrentMap中写值。
我理解应该只有一个线程向concurrentmap中写值。

  • 写回答

1条回答 默认 最新

  • 沅虹 2019-03-08 05:55
    关注

    当多个线程运行到下面代码的第一行时,首先由于ConcurrentHashMap的get方法实际上未加锁,if判断的结果在大多数线程中为真,于是if中语句被执行。
    而当多个线程运行到第二行时,此时更不存在加锁,结果同上。
    直到有线程运行到第3行时,map才会加锁,但此时已经为时已晚。

    if (StringUtils.isBlank(map.get("hello"))) {
      log.debug("{}线程没有读取到值,开始写值", Thread.currentThread().getName());
      map.put("hello", Thread.currentThread().getName());
    }
    

    以下是java11中ConcurrentHashMap的get方法源码

        public V get(Object key) {
            Node<K,V>[] tab; Node<K,V> e, p; int n, eh; K ek;
            int h = spread(key.hashCode());
            if ((tab = table) != null && (n = tab.length) > 0 &&
                    (e = tabAt(tab, (n - 1) & h)) != null) {
                if ((eh = e.hash) == h) {
                    if ((ek = e.key) == key || (ek != null && key.equals(ek)))
                        return e.val;
                }
                else if (eh < 0)
                    return (p = e.find(h, key)) != null ? p.val : null;
                while ((e = e.next) != null) {
                    if (e.hash == h &&
                            ((ek = e.key) == key || (ek != null && key.equals(ek))))
                        return e.val;
                }
            }
            return null;
        }
    
    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论

报告相同问题?

悬赏问题

  • ¥15 微信小程序协议怎么写
  • ¥15 c语言怎么用printf(“\b \b”)与getch()实现黑框里写入与删除?
  • ¥20 怎么用dlib库的算法识别小麦病虫害
  • ¥15 华为ensp模拟器中S5700交换机在配置过程中老是反复重启
  • ¥15 java写代码遇到问题,求帮助
  • ¥15 uniapp uview http 如何实现统一的请求异常信息提示?
  • ¥15 有了解d3和topogram.js库的吗?有偿请教
  • ¥100 任意维数的K均值聚类
  • ¥15 stamps做sbas-insar,时序沉降图怎么画
  • ¥15 买了个传感器,根据商家发的代码和步骤使用但是代码报错了不会改,有没有人可以看看