【问题标题】:Why did Goetz not use volatile boolean for Listing 7.20 again?为什么 Goetz 没有在清单 7.20 中再次使用 volatile boolean?
【发布时间】:2018-06-17 00:11:45
【问题描述】:

这是 Brian Goetz 的 Java Concurrency in Practice 中清单 7.20 中的代码:

public class CheckForMail {
    public boolean checkMail(Set<String> hosts, long timeout, TimeUnit unit)
            throws InterruptedException { 
        ExecutorService exec = Executors.newCachedThreadPool();
        final AtomicBoolean hasNewMail = new AtomicBoolean(false);

        try { 
            for (final String host : hosts)     
                exec.execute(new Runnable() { 
                    public void run() { 
                        if (checkMail(host)) hasNewMail.set(true);
                    }
                }); 
        } finally { 
            exec.shutdown();
            exec.awaitTermination(timeout, unit); 
        } 
        return hasNewMail.get();
    } 

    private boolean checkMail(String host) { // Check for mail return
        false;
    }
}

提到这段代码,Goetz 说“使用 AtomicBoolean 而不是 volatile 布尔值的原因是,为了从内部 Runnable 访问 hasMail 标志,它必须是最终的,这将排除修改它”(第 158 页)。

为什么它必须是最终的?你不能把它变成一个非最终的布尔变量吗?

【问题讨论】:

  • 问:那么“Goetz”是谁,你引用的这些数字是什么????无论如何:这是一篇很好的文章,描述了“a) Java volatile 是什么,你为什么需要它?b) “finalvolatile 有什么关系? javax0.wordpress.com/2016/09/21/final-volatile
  • Goetz 是一本非常棒的书籍 Java 并发实践的作者

标签: java multithreading concurrency final atomicboolean


【解决方案1】:

但是为什么它必须是最终的?你不能把它变成一个非最终的布尔变量吗?

hasNewMail 需要从内部的Runnable 访问,正如 Goetz 所说。这是一个内部类的实例。在最新版本的 Java 中,变量“实际上是最终的”是内部类访问词法封闭方法的局部变量的要求。我认为 Goetz 是在要求更强的时候写作的:变量确实是 final。 “有效最终”和final 之间的区别对于此目的并不重要,但是,无论哪种方式,都不能修改变量。

还要注意,Goetz 代码中的 AtomicBooleanfinal。它本身不能修改,但里面存储的值可以,程序就是这样工作的。

【讨论】:

  • 那么这个“Goetz”到底是谁?为什么没有人给出名字或头衔?
  • @paulsm4,那就是 Java 语言架构师 Brian Goetz。该列表来自他的书,Java Concurrency in Practice
  • @Joihn Bollinger - 谢谢 :)
  • @paulsm4:他也是active Stackoverflow user
  • @katiex7 - 感谢您使用作者引用更新您的帖子:code from listing 7.20 in Brian Goetz's Java Concurrency in Practice。它有帮助:)
【解决方案2】:

局部变量不能是易失的。如果您尝试进行该更改,您会看到这是一个编译错误。

顺便说一句,从 Java 8 开始,您不再需要将变量标记为 final;只要是effectively final(即在第一次之后没有设置),Java 都会接受它,就像你将它标记为 final 一样。

【讨论】:

  • 您的 Johns 的两个答案都获得了赞成票,但由于回复时间更快而接受了这一点,但两个答案都很棒。
  • Yshavit,如果可以的话,因为我不能再发帖 75 分钟。在清单 7.22 jcip.net/listings/WebCrawler.java TrackingExecutor exec 中是易变的,但我认为没有必要这样做。当然 CrawlTask​​ 在一个单独的线程中递归调用 submitCrawlTask​​ ,但是我不明白为什么 TrackintExecutor exec 的可见性是一个问题,如果在第一次在 start 方法中的循环中调用 submitCrawlTask​​ 保证之前发生,因为我们是第一次实例化 exec和调用 exec.execute
猜你喜欢
  • 1970-01-01
  • 2017-10-20
  • 2019-08-12
  • 1970-01-01
  • 1970-01-01
  • 2011-06-20
  • 2015-06-03
  • 1970-01-01
相关资源
最近更新 更多