Path: csiph.com!usenet.pasdenom.info!weretis.net!feeder4.news.weretis.net!eternal-september.org!feeder.eternal-september.org!mx02.eternal-september.org!.POSTED!not-for-mail From: Eric Sosman Newsgroups: comp.lang.java.programmer Subject: Re: javax.swing.Timer blocking program termination Date: Tue, 14 Jul 2015 15:51:55 -0400 Organization: A noiseless patient Spider Lines: 113 Message-ID: References: Mime-Version: 1.0 Content-Type: text/plain; charset=utf-8; format=flowed Content-Transfer-Encoding: 7bit Injection-Date: Tue, 14 Jul 2015 19:50:31 +0000 (UTC) Injection-Info: mx02.eternal-september.org; posting-host="858a9d65d95f4ea4d355bd116aa2cdbf"; logging-data="18466"; mail-complaints-to="abuse@eternal-september.org"; posting-account="U2FsdGVkX18t+NVLCsEh3UutnRyNjUrG" User-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64; rv:38.0) Gecko/20100101 Thunderbird/38.0.1 In-Reply-To: Cancel-Lock: sha1:o+XocM8FHcHJgGIF8LIJpuLFav0= Xref: csiph.com comp.lang.java.programmer:32021 On 7/14/2015 2:35 PM, Martin Gregorie wrote: > On Tue, 14 Jul 2015 10:55:20 -0400, Jeff Higgins wrote: > >> Makes perfect sense to me. >> But I'm still not sure how a <1 sec timer keeps the EDT alive while a >1 >> sec timer doesn't - barring explicit stops in windowClosing. >> > > It occurs to me that, the way Knute's original example works, that he > might have inadvertently set up a race condition because all the heavy > lifting involved in setting up the JFrame, i.e. loading a shedload of > classes and constructing instances from them all happens on the EDT and > that this might well take a second or so to complete and still be running > when the timer gets started. IOW, could the timer have fired its event > before the default close operation had been defined and would the timer > event have been ignored if it fired its event before the JFrame had been > completed and displayed? > > Of course, this may be a stupid idea, but it does fit the test results > which show a short timeout being ignored while a longer one does what > you'd expect. I don't *think* that's it, but like you I'm not sure. I've been experimenting with this modified version of Knute's code: import java.awt.EventQueue; import javax.swing.JFrame; import javax.swing.Timer; public class Test extends JFrame { public Test(int millis, boolean repeats) { Timer timer = new Timer(millis, event -> { }); timer.setRepeats(repeats); System.out.printf("%s: delay %d ms, repeats %s%n", timer, timer.getDelay(), timer.isRepeats()); setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE); setSize(400, 300); setVisible(true); timer.start(); } public static void main(String... args) { int millis = (args.length > 0) ? Integer.parseInt(args[0]) : 1000; boolean repeats = (args.length > 1) ? Boolean.parseBoolean(args[1]) : true; EventQueue.invokeLater(() -> new Test(millis, repeats)); } } On my system (Java 1.8.0_45-b14, Windows 7 64-bit), I observe: - With a repeating Timer and a delay > 1000 ms, the JVM exits 1-2 seconds after the frame closes. - With a repeating Timer and a delay == 1000 ms, the JVM exits 10-25 seconds after the frame closes. - With a repeating Timer and a delay < 1000 ms, the JVM keeps on running after the frame closes, until I lose patience (> 1 min) and kill it manually. - With a *non*-repeating timer, the JVM exits 1-2 seconds after the frame closes. Here's a possible explanation, entirely uncontaminated by actual facts: Suppose there's a bit of Java somewhere that monitors the EDT's health by polling at about 1 Hz. It asks "Hey, EDT, are you doing anything important?" As long as the JFrame is open, the EDT replies "Yeah, I've got windows open." The monitor says "Okey-doke" and goes about its other business. After the frame closes, the EDT's reply changes to "There's nothing open, but events are still coming along and I'm processing them." The monitor says "Ho-kay, you're still doing work" and dozes off again. But with a > 1000 ms delay, the EDT replies to the next query with "No windows, and no events since you last asked." The monitor then says "Okay, time to call it a day" and tells the EDT to pack it in. The EDT stops, the JVM sees there are no non-daemons running, and shutdown commences. With a delay of exactly 1000 ms there's a bit of a race between the monitor and the Timer, and several query-response cycles may pass before it Just So Happens that two queries bracket zero Timer events, hence the long and variable post-close shutdown time in this case. And with a delay < 1000 ms, the Timer *always* fires at least once between each pair of the monitor's queries, so the EDT *always* reports that it's still doing work. And with a non-repeating Timer the EDT reports right away that there's nothing afoot. That sort of mechanism would account for what we've seen so far -- but "would account for" doesn't imply "is True." The ancients explained that invisible gods and demons moved the planets by blowing on them, but nowadays such notions aren't widely accepted (outside of Washington DC). Still not a confirmation, but highly suggestive: I added addWindowListener(new WindowAdapter() { @Override public void windowClosed(WindowEvent evt) { timer.stop(); } }); in the constructor, and found that the JVM *always* exited promptly after the frame closed, no matter the Timer's delay or repeatability. It really, really looks like the endless train of Timer events is what's keeping the EDT alive. -- esosman@comcast-dot-net.invalid "Don't be afraid of work. Make work afraid of you." -- TLM