Подтвердить что ты не робот

Как приостановить, а затем возобновить поток?

Я утверждаю, что читаю о потоке, но я никогда не использовал. Поэтому я прошу вас:)

У меня есть два потока: A и B, где A управляет GUI, а B управляет логикой.

Я бы начал с A.

Затем, когда A нарисует графический интерфейс, я приостановил его, чтобы подождать B, которые достигают точки X в методе запуска.

И когда B достигает метода X в методе запуска, я приостанавливаю B и возобновляю A.

A и B совместно использовать некоторую переменную для управления графическим интерфейсом и логикой...

Могу ли я это сделать? если да, то как?:)

4b9b3361

Ответ 1

Используя методы wait() и notify():

wait() - Вызывает текущий поток ждать, пока другой поток не вызывает notify() метод или notifyAll() метод для этого объекта.

notify() - пробуждает единственный поток, который ожидает на этом мониторе объекта.

Ответ 2

Вы можете заблокировать потоки, используя методы wait и notify класса Object, но это может быть сложно сделать правильно. Вот пример внутри бесконечного цикла в Runnable:

public class Example implements Runnable {
    private volatile boolean running = true;
    private volatile boolean paused = false;
    private final Object pauseLock = new Object();

    @Override
    public void run() {
        while (running) {
            synchronized (pauseLock) {
                if (!running) { // may have changed while waiting to
                    // synchronize on pauseLock
                    break;
                }
                if (paused) {
                    try {
                        synchronized (pauseLock) {
                            pauseLock.wait(); // will cause this Thread to block until 
                            // another thread calls pauseLock.notifyAll()
                            // Note that calling wait() will 
                            // relinquish the synchronized lock that this 
                            // thread holds on pauseLock so another thread
                            // can acquire the lock to call notifyAll()
                            // (link with explanation below this code)
                        }
                    } catch (InterruptedException ex) {
                        break;
                    }
                    if (!running) { // running might have changed since we paused
                        break;
                    }
                }
            }
            // Your code here
        }
    }

    public void stop() {
        running = false;
        // you might also want to interrupt() the Thread that is 
        // running this Runnable, too, or perhaps call:
        resume();
        // to unblock
    }

    public void pause() {
        // you may want to throw an IllegalStateException if !running
        paused = true;
    }

    public void resume() {
        synchronized (pauseLock) {
            paused = false;
            pauseLock.notifyAll(); // Unblocks thread
        }
    }
};

(Для получения дополнительной информации о том, почему нам нужно синхронизировать, как показано выше, во время вызова wait и notifyAll, см. Учебник Java по этому вопросу.)

Если другой Поток вызывает этот метод Runnable pause(), то Поток, выполняющий runnable, заблокируется, когда достигнет вершины цикла while.

Обратите внимание, что невозможно приостановить поток в любой произвольной точке. Вам нужен поток, чтобы периодически проверять, должна ли она приостановиться и заблокировать себя, если это так.

Ответ 3

Я бы ожидал, что вам не нужно приостанавливать поток GUI. Операционная система позаботится об этом, и она должна быть готова ответить, если пользователь что-то сделает.

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

Ответ 4

вы можете использовать CountDownLatch. Когда Thread A должен ждать, пока Thread B вызовет countDownLatchInstance.await(); Когда B достигнет точки X, вы вызовете countDownLatchInstance.countDown(); позволяя A продолжить поток выполнения.

Когда вы говорите

A управляет графическим интерфейсом

Надеюсь, вы не ссылаетесь на UI/Main Thread

Ответ 5

То, как я получил поток, подождать и уведомить, работая на меня:

public class Main {

    public static void main(String[] args) {

        final Object lock = new Object();


        MyThread t = new MyThread();
        t.lock = lock;
        t.run();

        while (true) {
            try {
                synchronized (lock) {
                    lock.wait();
                }
                System.out.println("hello");
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
}

public class MyThread extends Thread {

    Object lock;

    @Override
    public void run() {

        JFrame fr = new JFrame("Anothing");
        JButton btn = new JButton("Next");
        btn.addActionListener(new ActionListener() {

            @Override
            public void actionPerformed(ActionEvent e) {
                synchronized (lock) {
                    lock.notify();
                }

            }
        });
        fr.setLayout(new FlowLayout());
        fr.add(btn);
        fr.setSize(400, 400);
        fr.setVisible(true);
    }
}

Затем, когда я нажимаю кнопку, другой поток просыпается, выполняет один раунд и ждет нового нажатия.

Ответ 6

Java-примитив для приостановки и возобновления потока устарел. Посмотрите это, чтобы понять, как вы можете добиться наилучшего, что вам нужно - http://docs.oracle.com/javase/7/docs/technotes/guides/concurrency/threadPrimitiveDeprecation.html Проверьте, как вы можете сделать эквивалент приостановки и возобновить

Что следует использовать вместо Thread.suspend и Thread.resume?

Как и в случае с Thread.stop, разумный подход заключается в том, чтобы опрос "целевой нити" включал переменную, указывающую желаемое состояние потока (активное или приостановленное). Когда желаемое состояние приостановлено, поток ожидает использования Object.wait. Когда поток возобновляется, целевой поток уведомляется с помощью Object.notify.

Пример кода приведен в том же ответе, который поможет вам достичь этого.