1

Here is the code from listing 7.20 in Brian Goetz's Java Concurrency in Practice:

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;
    }
}

Referring this code, Goetz says that "The reason an AtomicBoolean is used instead of a volatile boolean is that in order to access the hasMail flag from the inner Runnable, it would have to be final, which would preclude modifying it" (p. 158).

Why does it have to be final? Couldn't you just make it a non-final boolean volatile?

John Bollinger
  • 160,171
  • 8
  • 81
  • 157
katiex7
  • 863
  • 12
  • 23
  • Q: So who is "Goetz" and what are these numbers you're citing???? ANYWAY: here's an excellent article describing "a) What is Java `volatile`, and why would you ever need it?, and b) "How does `final` relate to `volatile`? https://javax0.wordpress.com/2016/09/21/final-volatile/ – paulsm4 Jan 08 '18 at 01:25
  • Goetz is an author for a really great book Java concurrency in practice – katiex7 Jan 08 '18 at 01:35

2 Answers2

6

However why does it have to be final? Couldn't you just make it a non final boolean volatile?

hasNewMail needs to be accessed from the inner Runnable, as Goetz says. That's an instance of an inner class. In the most recent versions of Java, the variable being "effectively final" is a requirement for an inner class to access a local variable of a lexically enclosing method. I think Goetz was writing at a time when the requirement was stronger: that the variable indeed be final. The difference between "effectively final" and final doesn't really matter for this purpose, however, as either way, the variable cannot be modified.

Note, too, that the AtomicBoolean in Goetz's code is final. It itself cannot be modified, but the value stored within can be, and this is how the program works.

John Bollinger
  • 160,171
  • 8
  • 81
  • 157
  • So who the heck is this "Goetz" guy? Why doesn't anybody give a first name, or a title? – paulsm4 Jan 08 '18 at 01:27
  • 5
    @paulsm4, that would be Java language architect [Brian Goetz](http://www.oracle.com/us/technologies/java/briangoetzchief-188795.html). The listing is from his book, [*Java Concurrency in Practice*](http://jcip.net/). – John Bollinger Jan 08 '18 at 01:30
  • @Joihn Bollinger - Thank you :) – paulsm4 Jan 08 '18 at 07:15
  • 1
    @paulsm4: he is also an [active Stackoverflow user](https://stackoverflow.com/users/3553087/brian-goetz). – Holger Jan 09 '18 at 18:44
  • @katiex7 - thank you for updating your post with the author citation: `code from listing 7.20 in Brian Goetz's Java Concurrency in Practice`. It helps :) – paulsm4 Jan 09 '18 at 23:57
3

Local variables can't be volatile. If you try to make that change, you'll see it's a compilation error.

Incidentally, as of Java 8, you no longer need to mark the variable as final; as long as it's effectively final (that is, you don't set it after the first time), Java will accept it as if you'd marked it final.

yshavit
  • 42,327
  • 7
  • 87
  • 124
  • Both your Johns answer got an upvote but accepted this due to faster reply time, but both answers are great. – katiex7 Jan 08 '18 at 01:30
  • Yshavit, if I may, since I cannot post for another 75minutes. In listing 7.22 http://jcip.net/listings/WebCrawler.java TrackingExecutor exec is volatile, but I see no need for this. Sure the CrawlTask calls submitCrawlTask in a separate thread recursively, but I cannot see why visibility of TrackintExecutor exec is an issue if there is a happens before guarantee on the first time submitCrawlTask is called in a loop in the start method since we are first instantiating exec and the calling exec.execute – katiex7 Jan 08 '18 at 01:42