首页 > 解决方案 > 这种结构有意义吗?

问题描述

面对一个带有此代码的项目:

   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 并没有强调这种结构毫无意义。

标签: javamultithreadingjava.util.concurrentatomicinteger

解决方案


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

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

在这种情况下,这样做的后果看起来并不是灾难性的——您可能会错过一些日志记录语句,并且您可能会看到一些意想不到的消息,例如Processing 101,然后想知道为什么这个数字不是 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()在“大量代码”之后放置。


推荐阅读