The message from this sender included one or more files which could not be scanned for virus detection; do not open these files unless you are certain of the sender's intent.
---------------------------------------------------------------------- On Sat, 27 Jun 2020 19:40:53 GMT, John Neffenger <github.com+1413266+jgn...@openjdk.org> wrote: >> OK, that seems fine then. I'll take a closer look and then finish my review. > >> OK, that seems fine then. I'll take a closer look and then finish my review. > > Actually, I think you may be right, though. Sorry for replying before looking > into it. I now think the > `ScheduledThreadPoolExecutor` should be shut down, but let me look into it a > bit more this afternoon before your final > review. Thanks! The new `ScheduledThreadPoolExecutor` is ~complicated~ > flexible! 😄 I think the code in the `_stop` method is correct after all. The `MonocleTimer` class is written to allow for multiple calls to the pair of `_start` and `_stop` methods (even though I don't think that ever happens), and the static `ScheduledThreadPoolExecutor`, named `scheduler`, is created only once and reused on subsequent calls. Changing the `_stop` method to call `task.cancel(true)` still leaves the timer thread running, which prevents the JavaFX application from exiting when the timer thread is a user thread. Furthermore, whether it's a user or daemon thread, if the call to `task.cancel(true)` happens to run exactly when the periodic task is *in progress*, the `timerRunnable` lambda in `QuantumToolkit` prints the stack trace when it catches the `InterruptedException`. java.lang.InterruptedException: at javafx.graphics/com.sun.javafx.tk.quantum.QuantumToolkit .lambda$runToolkit$12(QuantumToolkit.java:345) at java.base/java.util.concurrent.Executors$RunnableAdapter .call(Executors.java:515) at java.base/java.util.concurrent.FutureTask .runAndReset(FutureTask.java:305) at java.base/java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask .run(ScheduledThreadPoolExecutor.java:305) at java.base/java.util.concurrent.ThreadPoolExecutor .runWorker(ThreadPoolExecutor.java:1130) at java.base/java.util.concurrent.ThreadPoolExecutor$Worker .run(ThreadPoolExecutor.java:630) at java.base/java.lang.Thread .run(Thread.java:832) So the call to `task.cancel(false)` is correct. Changing the `_stop` method to shut down the `scheduler` will terminate the associated thread, regardless of its daemon status, but a subsequent call to `_start` will throw a `RejectedExecutionException` when trying to schedule the timer task: java.util.concurrent.RejectedExecutionException: Task java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask@b1fe89 [Not completed, task = java.util.concurrent.Executors$RunnableAdapter@1f85c96 [Wrapped task = com.sun.javafx.tk.quantum.QuantumToolkit$$Lambda$111/0x34563828@141859b]] rejected from java.util.concurrent.ScheduledThreadPoolExecutor@55f462 [Terminated, pool size = 0, active threads = 0, queued tasks = 0, completed tasks = 0] at java.base/java.util.concurrent.ThreadPoolExecutor$AbortPolicy .rejectedExecution(ThreadPoolExecutor.java:2057) at java.base/java.util.concurrent.ThreadPoolExecutor .reject(ThreadPoolExecutor.java:827) at java.base/java.util.concurrent.ScheduledThreadPoolExecutor .delayedExecute(ScheduledThreadPoolExecutor.java:340) at java.base/java.util.concurrent.ScheduledThreadPoolExecutor .scheduleAtFixedRate(ScheduledThreadPoolExecutor.java:632) at javafx.graphics/com.sun.glass.ui.monocle.MonocleTimer ._start(MonocleTimer.java:64) at javafx.graphics/com.sun.glass.ui.Timer .start(Timer.java:96) at javafx.graphics/com.sun.javafx.tk.quantum.QuantumToolkit .runToolkit(QuantumToolkit.java:384) at javafx.graphics/com.sun.javafx.tk.quantum.QuantumToolkit .lambda$startup$10(QuantumToolkit.java:280) at javafx.graphics/com.sun.glass.ui.Application .lambda$run$1(Application.java:153) at javafx.graphics/com.sun.glass.ui.monocle.RunnableProcessor .runLoop(RunnableProcessor.java:92) at javafx.graphics/com.sun.glass.ui.monocle.RunnableProcessor .run(RunnableProcessor.java:51) at java.base/java.lang.Thread .run(Thread.java:832) So if we want `MonocleTimer` to reuse a single `ScheduledThreadPoolExecutor` object, I think the only way to make sure that its timer thread exits when the application exits is to set its daemon status to `true`. ------------- PR: https://git.openjdk.java.net/jfx/pull/256