【问题标题】:Does this construction make sense?这种结构有意义吗?
【发布时间】:2020-01-22 08:50:39
【问题描述】:

遇到一个使用此代码的项目:

   public class IndexUpdater implements Runnable {
        @Override
        public void run() {
            final AtomicInteger count = new AtomicInteger(0);
            FindIterable<Document> iterable = mongoService.getDocuments(entryMeta, null, "guid");
                iterable.forEach(new Block<Document>() {
                    @Override
                    public void apply(final Document document) {
                        count.incrementAndGet();
                        // A lot of code....
                        if (count.get() / 100 * 100 == count.get()) {
                            LOG.info(String.format("Processing: %s", count.get()));
                        }
                    }
                });
        }
   }

这里我对三行代码感兴趣:

if (count.get() / 100 * 100 == count.get()) {
    LOG.info(String.format("Processing: %s", count.get()));
}

考虑到多线程和 AtomicInteger 变量的类型,这种情况是否有意义?或者这是一个毫无意义的检查? 有趣的是,IntellijIdea 并没有强调这种结构毫无意义。

【问题讨论】:

  • 我不明白 count.get() / 100 * 100 == count.get() 应该完成什么。你只是想检查count.get()%100==0吗?
  • 在两次调用中,count.get() 的值并不总是相同。使用count.get() % 100 == 0会更容易。
  • 考虑到“编写满足您需要的代码”的做法是没有意义的:它向下舍入到最接近的 100,然后打印四舍五入的数字是否是原始数字,所以.. . 为什么不打印count % 100 == 0,这是测试倍数的标准方法?
  • 考虑多线程:这里有多线程吗? forEach 真的在多个线程上执行 Block 吗?
  • “有趣的是,IntellijIdea 并没有强调这种结构毫无意义” Intellij 无法确定任意代码的意义。它只会标记“已知”模式。

标签: java multithreading java.util.concurrent atomicinteger


【解决方案1】:

我不会称这段代码“毫无意义”,而是错误(或者,它可能具有意想不到的语义)。

如果这是以多线程方式调用的,则在方法中的三个调用中count.get() 的值并不总是相同(如果包含count.incrementAndGet(),则有四个)。

this 的情况下,这样做的后果看起来并不严重 - 您可能会错过一些日志记录语句,并且您可能会看到一些意想不到的消息,例如 Processing 101,然后想知道为什么number 不是 100 的倍数。但如果您在其他地方使用相同的构造,可能会产生更重要的影响。

count.incrementAndGet() 的结果放入变量(*)中,以便以后使用。

但是,使用count.get() % 100 == 0 会更容易:

int value = count.incrementAndGet();
// A lot of code....
if (value % 100 == 0) {
  LOG.info(String.format("Processing: %s", value));
}

这是正确的(或者,它可能是预期的)并且更易于阅读。


(*) 根据您实际希望在此日志消息中显示的内容,您可能希望将 count.incrementAndGet() 放在“大量代码”之后。

【讨论】:

  • 仍然存在竞争条件,因为 OP 会调用 incrementAndGet(),然后是 get()。唯一的调用应该是 incrementAndGet()。
猜你喜欢
  • 2011-06-20
  • 1970-01-01
  • 2011-05-08
  • 2019-08-11
  • 1970-01-01
  • 1970-01-01
  • 2022-12-29
  • 2019-08-11
  • 1970-01-01
相关资源
最近更新 更多