user6866343
user6866343

Reputation:

What thread does sleep method interrupt?

After reading Java doc plus stackoverflow's answers no this question, i came to a thought that Thread.sleep() sleeps the current thread. Okay. How do i determine what is the current thread in my case?

When this code runs for the first time, it runs in a default thread which executes the main function. Am i right? So we sleep this thread for a second to allow the others threads to do their stuff.

After the invokeLater() is called, we start running the render method from the brand new thread so when we call Thread.sleep() the second time, we interrup this new thread while the default one is running without any kind of interruption. Am i missing something here?

The last thing i don't understand is that when i test this code, by calling Thread.sleep() it interrupts the whole Swing thing: GUI, events etc. That means that everything that is not Swing related in my program should run absolutely seamlessly but seems like it's not.

private void render() {
        if (bs == null) {
            createBufferStrategy(3);
            bs = getBufferStrategy();
        }

        g = bs.getDrawGraphics();
        g.setColor(Color.BLACK);
        g.fillRect(0, 0, getWidth(), getHeight());
        onRender(g);
        g.dispose();
        bs.show();

        try {
            Thread.sleep(1000);
        } catch (InterruptedException e) {
        }

        EventQueue.invokeLater(() -> render());
    }

Upvotes: 0

Views: 433

Answers (4)

Solomon Slow
Solomon Slow

Reputation: 27125

Thread.sleep() sleeps the current thread [but] How do i determine what is the current thread?

You misunderstand what "current thread" means. It means the thread that called the method.

Don't think of Thread.sleep(n) as doing anything to a thread. Think of it as a method that does nothing, and then returns n milliseconds later.

When i pass a runnable into invokeLater, i'm creating another thread and use its method run to call that render method. How is that possible?

invokeLater(r) puts r onto a queue. It also creates the EDT, but only if the EDT does not already exist. So, there will never be more than one EDT. The EDT eventually will pick r off the queue and call r.run().

In your case, r is created by the lambda expression, () -> render(). Every time your render() function is run, it will queue up a new Runnable(), and the EDT will almost immediately call render() again.

When i test this code, by calling Thread.sleep() it interrupts the whole Swing thing

ALL events are handled by the EDT. When the EDT calls your render() method, it can't do anything else---it can't handle any events---until render() returns. The sleep(1000) call insures that render() will not return for at least one full second. That is one full second during which your program will be unable to respond to any user input.

Since the EDT will be calling your render() function more or less continuously, that means that the EDT will spend almost all of its time sleeping, your program will be mostly unresponsive to user input.

Upvotes: 1

gabrielgiussi
gabrielgiussi

Reputation: 9575

Only the Swing main thread or event dispatch thread will execute the render method.

If you want that worker threads execute code you must tell them explicitly from the main thread.

   SwingWorker worker = new SwingWorker<ImageIcon[], Void>() {
    @Override
    public ImageIcon[] doInBackground() {
        final ImageIcon[] innerImgs = new ImageIcon[nimgs];
        for (int i = 0; i < nimgs; i++) {
            innerImgs[i] = loadImage(i+1);
        }
        return innerImgs;
    }

    @Override
    public void done() {
        //Remove the "Loading images" label.
        animator.removeAll();
        loopslot = -1;
        try {
            imgs = get();
        } catch (InterruptedException ignore) {}
        catch (java.util.concurrent.ExecutionException e) {
            String why = null;
            Throwable cause = e.getCause();
            if (cause != null) {
                why = cause.getMessage();
            } else {
                why = e.getMessage();
            }
            System.err.println("Error retrieving file: " + why);
        }
    }
};

For example you could span several SwingWorker and after that sleep the main thread.

Upvotes: 0

Zefick
Zefick

Reputation: 2119

The last thing i don't understand is that when i test this code, by calling Thread.sleep() it interrupts the whole Swing thing: GUI, events etc. That means that everything that is not Swing related in my program should run absolutely seamlessly but seems like it's not.

All UI events in Swing run in a single thread. Usually it is a main thread. If this thread are taken for some activity then whole UI will hang for some time. To avoid hanging do not make heavy calculation in listeners of UI controls.

Upvotes: 0

Mena
Mena

Reputation: 48404

A static invocation of Thread.sleep...

Causes the currently executing thread to sleep (temporarily cease execution) for the specified number of milliseconds, subject to the precision and accuracy of system timers and schedulers. The thread does not lose ownership of any monitors.

(bold statement underlined by me).

If you invoke it in a thread that seems to render some UI (or in general, in the main running thread), you will almost certainly see some degradation in usability.

Note that the concepts of a thread sleeping and interrupting a thread are different.

That's why you need to catch InterruptedException when invoking Thread.sleep, as the thread might be interrupted while sleeping, e.g. by another thread invoking interrupt on the sleeping thread.

Also note that a thread can interrupt itself as well, but that obviously would not happen while it's sleeping at the same time.

Also note in your case that render adds an ansynchronous invocation of itself through a new Runnable to the EventQueue recursively, which seems pretty dangerous.

Upvotes: 0

Related Questions