Почему эта тема ведет себя так странно? - PullRequest
0 голосов
/ 26 марта 2011

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

public static void main(final String[] args) throws InterruptedException {
        Executor exec = Executors.newSingleThreadExecutor();
        MyThread thread = new MyThread();
        exec.execute(thread);
        thread.pause();
        thread.pause(); // unpause
    }

Теперь давайте добавим немного спящего в поток, чтобы он на некоторое время приостановился:

public static void main(final String[] args) throws InterruptedException {
        Executor exec = Executors.newSingleThreadExecutor();
        MyThread thread = new MyThread();
        exec.execute(thread);
        thread.pause();
        Thread.sleep(500); 
        thread.pause(); // unpause
    }

Но этот код никогда не заканчивается.Почему?

Вот реализация метода pause, он проверяет закрытое логическое поле на паузу:

public synchronized void pause() {
        paused = (paused) ? false : true;
    }

А вот реализация переопределенного метода run:

@Override
    public void run() {
        // don't worry, I just need som dummy data to take some cpu time ;)
        PriorityQueue<Double> queue = new PriorityQueue<Double>();
        Random random = new Random(System.currentTimeMillis());
        System.out.println("I stared");
        checkPause();
        // let's do some big computation
        for (int i=0; i<10000000; i++) { // 10 mio
            System.out.println(i);
            queue.add(random.nextDouble());
            if (i % 3 == 0) {
                queue.poll(); // more complex operation
            }
        }
        System.out.println("I'm done");
    }

private void checkPause() {
        synchronized (this) {
            if (paused) {
                while (paused != false) {
                    try {
                        wait();
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            }
        }
    }

Когда я попробую отладить, я остановлюсь на методе wait().Тогда это просто ждет: /

Ответы [ 3 ]

3 голосов
/ 26 марта 2011

Когда вы вызываете wait(), ваш поток ожидает, пока другой поток не вызовет свой метод notify().

Вы не звоните notify() в теме из своей основной темы.

Также обратите внимание, что synchronize(this) - это то же самое, что и синхронизация метода; он использует сам объект в качестве замка. Как только ваш поток достигнет wait(), ваш основной поток заблокируется на thread.unpause(), потому что метод checkPause() заблокирован.

1 голос
/ 26 марта 2011

Я думаю, что в 1-м случае поток вообще не останавливается, потому что если нет Thread.sleep(500);, вероятно, оба pause() вызываются до checkPause(), и поток никогда не ждет.Во втором случае поток достигает значения checkPause(), когда pause = true и ожидает.поскольку никто не звонит notify(), он не будет продолжаться.

1 голос
/ 26 марта 2011

Я вижу wait(), но не вижу соответствующего вызова notify(), который снова разбудил бы поток.

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