Как заставить другой поток спать в Java - PullRequest
6 голосов
/ 02 октября 2009

У меня есть класс, который расширяет поток. Этот поток, когда работает, тратит большую часть своего времени на сон, он выполнит проверку, если true выполнит простое действие, затем будет спать в течение 1/2 секунды и повторить.

У класса также есть открытый метод, который вызывается другими потоками. Если это называется, я хочу, чтобы поток спал дольше, если он уже спал, или просто спал немедленно, если это не так. Я попытался использовать this.sleep, но, похоже, он все еще спит в текущем потоке и жалуется, что метод sleep является статическим и должен иметь статический доступ.

Эта программа показывает мою проблему, когда вызывается CauseSleep, я хочу, чтобы он прекратил печатать числа, пока этот сон не закончится.

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) {
            }
        }
    }
}

Я получаю вывод

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

Ответы [ 3 ]

24 голосов
/ 02 октября 2009

Вы не можете заставить другую нить спать. (Вы можете использовать устаревший метод suspend(), но не используйте его). Этот звонок:

this.sleep(200);

фактически заставит в текущий момент выполнять спящий поток, а не Thread, на который ссылается "this". sleep - статический метод - хорошие IDE выдают предупреждение по этой строке.

У вас должен быть просто флаг с надписью «спи, пожалуйста», а затем заставьте нить спящего проверить этот флаг перед выполнением любой работы.

Это хорошая вещь, которую нельзя заставить спать другой поток. Предположим, что это синхронизированный метод - это означает, что вы будете удерживать блокировку во время сна, в результате чего все остальные будут пытаться получить такую ​​же блокировку для блокировки. Не очень хорошая вещь. Используя систему на основе флагов, вы засыпаете контролируемым способом - в момент, когда вы знаете, что это не принесет вреда.

3 голосов
/ 02 октября 2009

Добавьте это к своей теме:

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

В run():

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

В другой теме:

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

Таким образом, вы можете заставить спящего ждать, пока другая работа не будет завершена.

1 голос
/ 02 октября 2009

На самом деле, чтобы сообщить потоку спать дольше , я предлагаю, чтобы ваш специальный метод запомнил этот факт в изменчивое поле. Затем интересующая нить должна прочитать эту переменную и дольше спать, если она установлена.

Теперь, чтобы вызвать немедленный сон , вы должны прервать поток. Это вызовет исключение, чтобы остановить текущую обработку. Теперь вы должны разобраться с этим ... Подумайте, действительно ли вы этого хотите.

Другим решением было бы, в активности нормального потока, также опросить переменную, как в первом случае, и перевести ее в спящий режим, если она установлена. Это не приведет к немедленному сну , но это может быть довольно быстро, и прерывание будет происходить в особых точках в вашем коде, где вы знаете, что можете остановиться, не нарушая ничего ...

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...