1

以下是 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 页) )。

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

4

2 回答 2

6

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

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

还要注意,AtomicBooleanGoetz 代码中的final. 它本身不能修改,但其中存储的值可以,这就是程序的工作方式。

于 2018-01-08T01:24:15.030 回答
3

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

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

于 2018-01-08T01:20:46.363 回答