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 java 操作 elasticsearch 8.1 实现 索引的重建
  • ¥15 数据可视化Python
  • ¥15 要给毕业设计添加扫码登录的功能!!有偿
  • ¥15 kafka 分区副本增加会导致消息丢失或者不可用吗?
  • ¥15 微信公众号自制会员卡没有收款渠道啊
  • ¥15 stable diffusion
  • ¥100 Jenkins自动化部署—悬赏100元
  • ¥15 关于#python#的问题:求帮写python代码
  • ¥20 MATLAB画图图形出现上下震荡的线条
  • ¥15 关于#windows#的问题:怎么用WIN 11系统的电脑 克隆WIN NT3.51-4.0系统的硬盘