Почему Гетц снова не использовал volatile boolean для Листинга 7.20?

Вот код из листинга 7.20 в " Практическом параллелизме" Брайана Гетца на Java:

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

Ссылаясь на этот код, Гетц говорит, что "причина, по которой AtomicBoolean используется вместо энергозависимого логического значения, заключается в том, что для доступа к флагу hasMail из внутреннего Runnable он должен быть окончательным, что исключает его изменение" (стр. 158).

Почему это должно быть окончательным? Не могли бы вы просто сделать его неконечным логическим значением volatile?

2 ответа

Решение

Локальные переменные не могут быть изменчивыми. Если вы попытаетесь внести это изменение, вы увидите, что это ошибка компиляции.

Кстати, в Java 8 вам больше не нужно помечать переменную как final; до тех пор, пока он фактически окончательный (то есть вы не устанавливаете его после первого раза), Java примет его так, как если бы вы пометили его как окончательный.

Однако почему это должно быть окончательным? Не могли бы вы просто сделать его не финальным логическим значением volatile?

hasNewMail должен быть доступен изнутри Runnable, как говорит Гетц. Это пример внутреннего класса. В самых последних версиях Java переменная, являющаяся "эффективно конечной", является требованием для внутреннего класса для доступа к локальной переменной лексически заключающего в себе метода. Я думаю, что Гетц писал в то время, когда требование было сильнее: переменная действительно должна быть final, Разница между "эффективно окончательным" и final однако для этой цели это не имеет значения, так как переменная не может быть изменена.

Обратите внимание, что AtomicBoolean в коде Гетца есть final, Само по себе это не может быть изменено, но значение, хранимое внутри, может быть, и именно так работает программа.

Другие вопросы по тегам