What prevents a program from exiting the program?

I wrote like this.

public static void main(String[] args){ Thread thread = new Thread(() -> { while(true){ try{ // do something Thread.sleep(10); }catch(InterruptedException ex){ System.out.println("ABC"); break; } } }); JFrame frame = new JFrame(); frame.setSize(1280,720); frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE); frame.addWindowListener(new WindowAdapter(){ @Override public void windowClosed(WindowEvent e){ thread.interrupt(); } }); thread.start(); frame.setVisible(true); } 

When I clicked the close button on the window,
The program took several seconds to finish.
What prevents the exit of the program? And how can I close the program right away without using JFrame.EXIT_ON_CLOSE ?

I think my thread ( while(true) thread) ends immediately
because "ABC" is displayed shortly after clicking the close button.

Thanks.

EDIT

The same thing happened without my flow.

 public static void main(String[] args){ JFrame frame = new JFrame(); frame.setSize(1280,720); frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE); frame.setVisible(true); } 

EDIT2

 public static void main(String[] args){ Runtime.getRuntime().addShutdownHook(new Thread(() -> { Thread[] threads = new Thread[5]; Thread.enumerate(threads); System.out.println(Arrays.toString(threads)); System.err.println(LocalDateTime.now() + " SHUTDOWN"); } )); JFrame frame = new JFrame(); frame.setSize(1280,720); frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE); frame.addWindowListener(new WindowAdapter(){ @Override public void windowClosed(WindowEvent e){ Thread[] threads = new Thread[5]; Thread.enumerate(threads); System.out.println(Arrays.toString(threads)); System.err.println(LocalDateTime.now() + " CLOSE"); } }); frame.setVisible(true); } 

the conclusion was:

 [Thread[AWT-EventQueue-0,6,main], Thread[DestroyJavaVM,5,main], null, null, null] 2016-08-02T19:04:50.465 CLOSE [Thread[DestroyJavaVM,5,main], Thread[Thread-0,5,main], null, null, null] 2016-08-02T19:04:51.762 SHUTDOWN 
+5
source share
3 answers

While System.exit() should be used with caution, the Swing documentation explicitly indicates that this is the correct approach in scripting, as shown in the question:

When the last window displayed in the Java virtual machine (VM) is deleted, the virtual machine may terminate. Please note, however, that there may be a delay before the program automatically exits , and in some cases the program may continue to work. It is faster and safer to explicitly exit the program using System.exit(int) .

The following example does not display the delay between the close operation and the shutdown hook. When you delete a call to System.exit(0) delay is approx. There are 1.3 seconds:

 package com.example.swing; import java.awt.event.WindowAdapter; import java.awt.event.WindowEvent; import java.time.LocalDateTime; import javax.swing.JFrame; import javax.swing.SwingUtilities; public class ExitDelay { public static void main(String[] args){ Runtime.getRuntime().addShutdownHook(new Thread(() -> System.err.println(LocalDateTime.now() + " SHUTDOWN") )); SwingUtilities.invokeLater(() -> { JFrame frame = new JFrame(); frame.setSize(1280,720); frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE); frame.addWindowListener(new WindowAdapter(){ @Override public void windowClosed(WindowEvent e){ System.err.println(LocalDateTime.now() + " CLOSE"); // Do all required cleanup stuff. // check that threads are done, close files, commit transactions etc. // ... System.exit(0); } }); frame.setVisible(true); }); } } 
+6
source

To exit the program immediately, you can use System.exit(0) .

Like:

 public static void main(String[] args){ Thread thread = new Thread(() -> { while(true){ try{ // do something Thread.sleep(10); }catch(InterruptedException ex){ System.out.println("ABC"); System.exit(0); } } }); JFrame frame = new JFrame(); frame.setSize(1280,720); frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE); frame.addWindowListener(new WindowAdapter(){ @Override public void windowClosed(WindowEvent e){ thread.interrupt(); } }); thread.start(); frame.setVisible(true); } 
0
source

You are using DISPOSE_ON_CLOSE and this makes sense because EXIT_ON_CLOSE will use System.exit to close the jvm process with all active threads. A JFrame is a complex structure that uses some native calls to register callbacks for mouse events in your operating system. Thus, a clean exit takes some time. In addition, the garbage collector needs some time to discover that the AWT-Thread that launches the JFrame completes with a cleanup before it kills it. Therefore, I think 1.3 seconds is acceptable to cleanly process your application.
But if you really want to do this, you can force the end with another Thread , which simply checks continuously if all running threads have completed and all JFrames have disappeared. And if so, then this calls the great evil System.exit .


 final JFrame frame = new JFrame(); // make your JFrame final final Thread thread = new Thread(() ... // make your Thread final 

and add this end to check the flow

 final Thread endChecker = new Thread(() -> { while(true){ try{ Thread.sleep(100); if(!frame.isDisplayable() && !thread.isAlive()) System.exit(0); }catch(InterruptedException ex){ break; } } }); endChecker.start(); 
0
source

All Articles