title: JavaFX 2.1 and threads? -or- Ending a JavaFX application gracefully?
body: <p>I wanted a really simple way to play an mp3 file from a Java application.  After some research I found that the newest versions of Java 7 SE are packaged with JavaFX, so I thought I would try.  This question is NOT about playing mp3 files, but about getting JavaFX to work in a well-behaved way.</p>
  
  <p>So, in my first experiment with JavaFX, I used some code suggested in a post to stackoverflow (<a href="https://stackoverflow.com/questions/6045384/playing-mp3-and-wav-in-java">see here</a>) and created, essentially, the following test program:</p>
  
  <pre><code>import javafx.application.Application;
  import javafx.stage.Stage;
  import javafx.scene.media.Media;
  import javafx.scene.media.MediaPlayer;
  
  public class progtest extends Application
  {
  
      /*---------------------------------------------------------*\
          FUNCTION:  main()
      \*---------------------------------------------------------*/
      public static void main(String args[])
      {
  
          launch(args);
  
      } /* END:  main() */
  
      /*---------------------------------------------------------*\
          FUNCTION:  start()
      \*---------------------------------------------------------*/
      @Override
      public void start(Stage stage)
      {
  
          Media medMsg 
              = 
              new Media(getClass().getResource("msg.mp3").toExternalForm());
          MediaPlayer medplMsg = new MediaPlayer(medMsg);
          medplMsg.play();
  
          System.out.println("Here.\n");
  
      } /* END:  start() */
  
  }
  </code></pre>
  
  <p>(This is slightly more sophisticated than my original test program:  this version came about after suggestions from jewelsea made in response to an earlier question I posted about getting the program running at all (<a href="https://stackoverflow.com/questions/10888367/compiling-and-running-with-javafx-2-1">see here</a>).)</p>
  
  <p>To compile this code I used:</p>
  
  <pre><code>javac -cp "c:\Program Files\Oracle\JavaFX 2.1 Runtime\lib\jfxrt.jar";..\bin -d ..\bin ..\src\progtest.java
  </code></pre>
  
  <p>And, to run the code I went into my ..\bin directory and used:</p>
  
  <pre><code>java -cp .;"c:\Program Files\Oracle\JavaFX 2.1 Runtime\lib\jfxrt.jar" progtest
  </code></pre>
  
  <p>This program runs and plays the clip plays.  However, the program doesn't return to the command prompt unless I do a Ctrl-C.</p>
  
  <p>That behavior seemed like some sort of thread issue.  I have seen this sort of behavior many times working with Java threads (which, sadly, have real problems allowing for graceful exits from programs).</p>
  
  <p>So, I thought, perhaps if I put the code in its own thread and then end the program's main thread when that thread ends, things would be okay.  (I could see that this wasn't wholly a cogent thought, but anyway, I thought I would try.)  So, I wrote the following second version of the code:</p>
  
  <p>Here is the main thread:</p>
  
  <pre><code>import javafx.application.Application;
  import javafx.stage.Stage;
  import Msg.*;
  
  public class progtest2 extends Application
  {
  
      /*---------------------------------------------------------*\
          FUNCTION:  main()
      \*---------------------------------------------------------*/
      public static void main(String args[])
      {
  
          launch(args);
  
      } /* END:  main() */
  
      /*---------------------------------------------------------*\
          FUNCTION:  start()
      \*---------------------------------------------------------*/
      @Override
      public void start(Stage stage)
      {
  
          Msg msgTime = new Msg();
          msgTime.passClass(getClass());
          msgTime.start();
  
          try
          {
              msgTime.join();
          }
          catch (InterruptedException e)
          {
          }
  
          System.out.println("Here.\n");
  
      } /* END:  start() */
  
  }
  </code></pre>
  
  <p>And here is the code for the Msg thread that should actually play the mp3 file:</p>
  
  <pre><code>package Msg;
  
  import KeyIO.*;
  import javafx.application.Application;
  import javafx.scene.media.Media;
  import javafx.scene.media.MediaPlayer;
  
  public class Msg extends Thread
  {
  
      private Class classRt = null;
  
      /*--------------------------------------------------------*\
          FUNCTION:  passClass()
      \*--------------------------------------------------------*/
      public void passClass(Class rt)
      {
  
          classRt = rt;
  
      } /* END:  passClass() */
  
      /*--------------------------------------------------------*\
          FUNCTION:  run()
      \*--------------------------------------------------------*/
      public void run()
      {
  
          Media medMsg
              = new Media(classRt.getResource("msg.mp3").toExternalForm());
          MediaPlayer medplMsg = new MediaPlayer(medMsg);
          medplMsg.play();
  
          System.out.println("Leaving Msg thread.\n");
  
      } /* END:  run() */
  
  }
  </code></pre>
  
  <p>(I built and ran these files with the same command (mutatis mutandis re the filenames and classnames) as above.)</p>
  
  <p>The program runs and plays the mp3 file.  Before you hear the file, you see "Leaving Msg thread." and then "Here.", which as you can see come from the Msg thread and the main thread respectively.  But, again, the program doesn't end.  I have to hit Ctrl-C to return to the command prompt.</p>
  
  <p>I put a System.exit() call right at the end of the main thread there just to see what the behavior would be.  The behavior was that the clip was not heard.  It seemed like the System.exit() call ended the process before the clip was played.</p>
  
  <p>So, next I tried putting the following lines in between the System.out.println("Here.\n"); and the System.exit() call I made:</p>
  
  <pre><code>System.out.print("Press ENTER to end...");
  KeyIO.ReadLine();
  </code></pre>
  
  <p>(KeyIO is a class I made just for doing keyboard input output simply.  The details are not really relevant here.)</p>
  
  <p>I figured that this would simply block the main thread from going forward until the clip played.</p>
  
  <p>But, no.  Instead, the clip didn't play.  When I hit ENTER, the program exited without playing the clip.</p>
  
  <p>Okay, so now I left that keyboard-input blocking code in, but I took out the System.exit() call.  Now the audio clip played, but the program didn't end again.</p>
  
  <p>Urgh!</p>
  
  <p>Any ideas how to gracefully get this to work in the way that it is sort of obvious one would want it to work?  I just want to make a call to play the clip, and then I want to be able to end the program.</p>
  
  <p>Thank you in advance!</p>