Ну, я понимаю, что в этой задаче всего одна не final переменная, что автоматически делает ее "жертвой" необходимости обозвать ее volatile.
Но вот с точки зрения программы - что это дает? Данная переменная (debugLifecycle) нигде не изменяется и от того, что нити будут читать ее значение, ровным счетом же ничего и никогда не поменяется. Ну то есть, что нить использует значение этой переменной из кэша, что из оперативной памяти - разницы никакой, так как это будет всегда одно и тоже значение.
По-моему, в данной задаче условию "Расставь volatile там, где необходимо." соответствует отсутствие каких-либо изменений, так как необходимости в применении volatile в данной задаче нет.
public class Solution extends Thread {
public static final String DEFAULT_JAVARUSH_THREAD_NAME = "JavaRushThread";
private static final AtomicInteger createdThreadIndex = new AtomicInteger();
private static final AtomicInteger aliveThreadIndex = new AtomicInteger();
static {
System.setProperty("java.util.logging.SimpleFormatter.format", "%1$tF %1$tT %4$s %2$s %5$s%6$s%n");
}
private static final Logger log = Logger.getLogger(Solution.class.getName());
private static volatile boolean debugLifecycle = true;
public Solution() {
this(DEFAULT_JAVARUSH_THREAD_NAME);
}
public Solution(String name) {
super(name + "-" + createdThreadIndex.incrementAndGet());
setUncaughtExceptionHandler(new UncaughtExceptionHandler() {
public void uncaughtException(Thread t, Throwable e) {
log.log(Level.SEVERE, "An error occurred in thread " + t.getName(), e);
}
});
}
public static void main(String[] args) {
new Solution().start();
new Solution().start();
new Solution().start();
}
public void run() {
// Copy debug flag to ensure consistent value throughout.
boolean debug = debugLifecycle;
if (debug) {
log.log(Level.INFO, "Created " + getName());
}
try {
aliveThreadIndex.incrementAndGet();
log.log(Level.INFO, "Thread " + getName() + " in progress...");
throw new RuntimeException("Oops " + getName());
} finally {
aliveThreadIndex.decrementAndGet();
if (debug) {
log.log(Level.INFO, "Exiting " + getName());
}
}
}
}