Make a popup window that will stay open for 3 seconds I am doing an assignment and I have a task where I need to make a simulation where under certain conditions it opens a popup window and then closes it after 3 seconds. This is how I did it:

if(condition) {
    ExecutorService executor = Executors.newSingleThreadExecutor();
    executor.submit(() -&gt; {
        Platform.runLater( () -&gt; {
            try {
                Monument atr = ((Monument)matrica[red][kolona]);
                FXMLLoader loader = new FXMLLoader(getClass().getResource("PopUp.fxml"));
                Scene scene = new Scene(loader.load());
                loader.&lt;PopUpController&gt;getController().setImage(atr.getImage());
                Stage stage = new Stage();
                stage.setScene(scene);
                stage.sizeToScene();
                stage.setResizable(false);
                stage.setTitle("Image");
                stage.show();
                sleep(3000);
                ((Stage)(stage.getScene().getWindow())).close();
            } catch (IOException | InterruptedException e) {
                e.printStackTrace();
            }
        });
    });
    executor.shutdown();
}


I use Platform.runLater because I am accessing the UI from a different thread. My question is, is there any better way of doing this?
Alternative code:

ScheduledExecutorService executor =  Executors.newSingleThreadScheduledExecutor();
// assuming the stage-setup is perfomed already:
executor.submit(() -&gt; Platform.runLater(stage::show));
executor.schedule(
    () -&gt; Platform.runLater(((Stage)stage.getScene().getWindow()).close())
    , 3
    , TimeUnit.SECONDS);


This approach has multiple advantages:


The (costly) stage-setup is moved away from the UI Thread
Sleeping on the UI Thread doesn't happen, freeing it to do actual work
ScheduledExecutorService is more exact with it's scheduling than a sleep-call. It also doesn't involve having to handle InterruptedException or spurious wakeup


But it also has one glaring disadvantage:


You can't directly shutdown the ExecutorService, because that would cancel the scheduled Runnable.


This shouldn't be much of a problem though, since you should not be creating an ExecutorService in method scope in the first place.
Instead you should move multithreading facilities into the class scope (or even into static scope), so as to enable easy cleanup when the application is terminated or the instance reaches the end of it's lifetime.