views:

117

answers:

3

Here is the code:

import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;

import javax.swing.JFrame;
import javax.swing.Timer;

public class TimerSample {
  public static void main(String args[]) {
    new JFrame().setVisible(true);
    ActionListener actionListener = new ActionListener() {
      public void actionPerformed(ActionEvent actionEvent) {
        System.out.println("Hello World Timer");
      }
    };
    Timer timer = new Timer(500, actionListener);
    timer.start();
  }
}

It generates a window and then periodically prints "Hello World Timer" in the terminal (Command Prompt). If I comment this line new JFrame().setVisible(true); the application does not print anything to the command line. Why?

ADDED:

I am not sure that I understand the answers correctly. As far as I understood, the timer starts a new thread. And this new thread exists simultaneously with the "main" thread. When the "main" thread is finished (when everything is done and there is nothing to do anymore) the whole application is terminated (together with the "new" thread created by the timer). Is right?

ADDED 2:

The above described explanation still does not explain everything. For example, the program works if I comment the new JFrame().setVisible(true); and put try {Thread.sleep(20000);} catch(InterruptedException e) {}; after the the timer.start(). So, I kind of understand that. With the sleep we keep the "main" thread busy so the thread created by the timer can exist. But new JFrame().setVisible(true); do not occupy the "main". As far as I understand it creates its own thread (like Timer). So, why thread of the JFrame can exist without the main thread and thread of timer cannot?

+1  A: 

The timer function is called in the window event loop (where also stuff like resizing, moving, repainting etc. is taken care of). Apparently if the window is hidden, the event loop is not executed.

This is wrong, check Frank's answer instead.

sisis
But why it is called in the "window event loop"? I do not see any place in the code where JFrame is somehow connected to Timer.
Roman
-1, it's not about hiding the window, but not creating it. If no window is created the main method exits, which is the real problem here (see my answer)
Frank
+3  A: 

You're missing the point. The Timer is independent from the window you created and it works also when you comment out that window creation line.

However, what you failed to see is: your main program exits after timer.start(), hence, your program execution is terminated and along with it goes the timer.

You can verify this if you add Thread.sleep(20000); at the end (including the required exception handling), or any other code that takes some time. Then your timer works just fine even without any window being created.

The point is that the JFrame, even when nothing is displayed, remains active, which in turn keeps your timer alive.

Frank
Frank, what do you mean under your main program "exits after" timer.start()? timer.start() exists not before main program but in the main program.
Roman
What do you mean by "your program execution is terminated"? When it is terminated? I start my program and it works before I terminate it (by closing the window and pressing Ctrl-C in the command prompt).
Roman
The timer works differently than a sleep. A sleep pauses the code for the specified time and then allows the next line to execute. The timer is non-blocking and triggers the event when that amount of time has passed. When you have a frame, there are other things happening in the program after main finishes, but with out it, your program terminates before the amount of time passes.
unholysampler
unholysampler, do i correctly understood? The timer start a new Thread. And this new thread exists simultaneously with the "main" thread. When the "main" thread is terminated (for example when everything is done and there is nothing to do anymore) the whole application is terminated (together with the "new" thread created by the timer).
Roman
A: 

Corresponding to each Timer object is a single background thread that is used to execute all of the timer's tasks, sequentially.

After the last live reference to a Timer object goes away and all outstanding tasks have completed execution, the timer's task execution thread terminates gracefully (and becomes subject to garbage collection). However, this can take arbitrarily long to occur. By default, the task execution thread does not run as a daemon thread, so it is capable of keeping an application from terminating. If a caller wants to terminate a timer's task execution thread rapidly, the caller should invoke the the timer's cancel method.1

So what does the java.util.Timer has to do with the javax.swing.Timer you might ask?

In v 1.3, another Timer class was added to the Java platform: java.util.Timer. Both it and javax.swing.Timer provide the same basic functionality 2

So your last reference to the timer goes away before your timer really starts... if you notice your main method completes as soon as you call timer.start(); and unless there is something that will keep your main thread alive until the timer starts, then your timer might never start.

In the first example the JFrame is keeping your main thread alive.

In the second example you sleep long enough for the timer to start and then the timer causes the main thread to stay alive:

public static void main(String args[]) {
        //new JFrame().setVisible(true);
        ActionListener actionListener = new ActionListener() {
            public void actionPerformed(ActionEvent actionEvent) {
                System.out.println("Hello World Timer");
            }
        };
        Timer timer = new Timer(500, actionListener);
        timer.start();
        try {
            Thread.sleep(500);//<--- the timer will still die
            Thread.sleep(100);//<--- sleep for another 100 and the timer will start printing although you can't rely on it
        } catch (InterruptedException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }
Lirik