Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to make another thread sleep in Java

I have a class that extends Thread. This thread when running spends most of it's time sleeping, it will perform a check, if true perform a simple action, then sleep for 1/2 second and repeat.

The class also has a public method that is called by other threads. If this is called I want the thread to sleep for longer if it is already sleeping or just sleep immediately if it isn't. I tried to have this.sleep but it seems that this still sleeps the current thread and it complains that the method sleep is static and should be accesses statically.

This program shows my problem, when CauseSleep is called I want it to stop printing numbers until that sleep has finished.

public class Sleeper {
    public static void main(String[] args) {
        new Sleeper();
    }
    public Sleeper() {
        System.out.println("Creating T");
        T t = new T();
        System.out.println("Causing sleep");
        t.CauseSleep();
        System.out.println("Sleep caused");
    }
    public class T extends Thread {
        public T() {
            this.start();
        }
        public void run() {
            for (int i = 0; i < 30; i++) {
                System.out.println("T Thread: " + i);
                try {
                    Thread.sleep(100);
                } catch (InterruptedException e) {
                }
            }
        }
        public void CauseSleep() {
            try {
                this.sleep(2000);
            } catch (InterruptedException e) {
            }
        }
    }
}

The output I get is

Creating T
Causing sleep
T Thread: 0
T Thread: 1
T Thread: 2
T Thread: 3
T Thread: 4
T Thread: 5
T Thread: 6
T Thread: 7
T Thread: 8
T Thread: 9
T Thread: 10
T Thread: 11
T Thread: 12
T Thread: 13
T Thread: 14
T Thread: 15
T Thread: 16
T Thread: 17
T Thread: 18
Sleep caused
T Thread: 19
T Thread: 20
T Thread: 21
T Thread: 22
T Thread: 23
T Thread: 24
T Thread: 25
T Thread: 26
T Thread: 27
T Thread: 28
T Thread: 29
like image 574
A Jackson Avatar asked Oct 02 '09 08:10

A Jackson


People also ask

Can sleep () method causes another thread to sleep?

Note that sleep is a static method, which means that it always affects the current thread (the one that is executing the sleep method). A common mistake is to call t. sleep() where t is a different thread; even then, it is the current thread that will sleep, not the t thread.

How do you put threads to sleep?

Answer: When calling sleep() method to put the thread to sleep, we always call it using the Thread class. For example, Thread. sleep (1000);

Which command makes thread sleep?

sleep() Method: Method Whenever Thread. sleep() functions to execute, it always pauses the current thread execution. If any other thread interrupts when the thread is sleeping, then InterruptedException will be thrown.


3 Answers

You can't make another thread sleep. (You can use the deprecated suspend() method, but please don't). This call:

this.sleep(200);

will actually make the currently executing thread sleep - not the Thread referred to by "this". sleep is a static method - good IDEs will issue a warning over that line.

You should just have a flag saying "sleep please" and then make the sleeper thread check that flag before doing any work.

It's a good thing that you can't cause another thread to sleep. Suppose it's in a synchronized method - that would mean you'd be holding a lock while sleeping, causing everyone else trying to acquire the same lock to block. Not a good thing. By using a flag-based system, you get to sleep in a controlled way - at a point where you know it's going to do no harm.

like image 181
Jon Skeet Avatar answered Sep 19 '22 04:09

Jon Skeet


Add this to your thread:

public AtomicBoolean waitLonger = new AtomicBoolean  ();
public Object lock = new Object ();

In run():

synchronized (lock) {
    if (waitLonger.get ()) {
        lock.wait ();
    }
}

In the other thread:

synchronized (lock) {
try {
    sleeper.waitLonger.set(true);
    ...
    lock.notify();
    sleeper.waitLonger.set(false);
}

This way, you can make the sleeper wait until the other work has completed.

like image 29
Aaron Digulla Avatar answered Sep 20 '22 04:09

Aaron Digulla


Actually, to tell the thread to sleep longer, I suggest that your special method would memorize this fact into a volatile field. Then, the thread of interest should read that variable, and sleep longer if set.

Now, to cause it to sleep immediately, you have to interrupt the thread. That will throw an exception, to stop the current processing. Now you have to deal with this ... Think if this is really what you want.

Another solution would be, in the thread normal's activity, to also poll the variable like in the first case, and to sleep if it is set. This would not cause an immediate sleep, but it could be pretty fast, and the interruption would be at special points in your code where you know you can stop without breaking things ...

like image 34
KLE Avatar answered Sep 19 '22 04:09

KLE