49

我声明我读过有关线程的信息,但我从未使用过。所以我问你:)

我有两个线程:AB,其中A管理 GUI,并B管理逻辑。

我会从A.

然后在A绘制 GUI 时,我会暂停它,等待B到达 X 点进入运行方法。

B到达 X 点进入 run 方法时,我 pauseB和 resume A

AB共享一些变量来管理 GUI 和逻辑......

我可以做吗?如果是,如何?:)

4

7 回答 7

28

使用wait()方法notify()

wait()- 使当前线程等待,直到另一个线程调用 该对象的notify()方法或notifyAll()方法。

notify()- 唤醒正在此对象的监视器上等待的单个线程。

于 2013-05-26T10:34:51.690 回答
24

wait您可以使用 Object 类的和方法阻塞线程notify,但要正确处理可能会很棘手。这是 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
        }
    }
};

(有关为什么在调用waitand时我们需要如上所示进行同步的更多信息notifyAll,请参阅有关该主题的 Java 教程。)

如果另一个 Thread 调用这个 Runnable 的pause()方法,那么运行 runnable 的 Thread 将在它到达 while 循环的顶部时阻塞。

请注意,不可能在任意点暂停线程。您需要 Thread 定期检查它是否应该暂停并自行阻塞。

于 2016-06-01T10:19:52.620 回答
4

我希望您不需要暂停 GUI 线程。操作系统会处理这个问题,并且它需要准备好在用户做某事时做出响应。

另一种想法是确保共享变量在两个线程之间正确同步。我最近尝试回答与此相关的问题,请参见此处

于 2013-05-26T10:39:37.813 回答
4

你可以使用一个CountDownLatch. 当线程 A 必须等待时,线程 B 将调用countDownLatchInstance.await();当 B 到达 X 点时将调用countDownLatchInstance.countDown();允许 A 继续其执行流程。

当你说

A 管理 GUI

希望你不要参考UI/Main Thread

,

于 2013-05-26T10:44:19.410 回答
2

这就是我让线程等待并通知为我工作的方式:

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

然后,每当我按下按钮时,另一个线程就会唤醒,执行一轮并等待新的点击。

于 2016-06-22T21:41:18.107 回答
2
public class Mutex {
    private final AtomicBoolean lock;
    private final Object mutex;

    public Mutex(boolean lock) {
        this.lock = new AtomicBoolean(lock);
        this.mutex = new Object();
    }

    public void step() {
        if (lock.get()) synchronized(mutex) {
            try {
                mutex.wait();
            } catch (InterruptedException ex) {}
        }
    }

    public void lock() {
        lock.set(true);
    }

    public void unlock() {
        lock.set(false);

        synchronized(mutex) {
            mutex.notify();
        }
    }
}

只需将 Mutex 对象添加到您的线程并制作 getter。

public class MyThread extends Thread {
    private final Mutex mutex;

    public MyThread() {
        this.mutex = new Mutex(false);
    }

    public Mutex getMutex() {
        return this.mutex;
    }

    @Override
    public void run() {
        while (!isInterrupted()) {
            mutex.step();

            // do your code
        }
    }
}

如果你想暂停线程只需调用

myThread.getMutex().lock();

如果你想恢复线程只需调用

myThread.getMutex().unlock();
于 2020-06-09T16:38:56.340 回答
0

不推荐使用暂停和恢复线程的 java 原语。请参阅此内容以了解如何实现所需的最佳效果 - http://docs.oracle.com/javase/7/docs/technotes/guides/concurrency/threadPrimitiveDeprecation.html 检查如何执行相当于暂停和恢复的操作

我应该使用什么来代替Thread.suspendand Thread.resume

与 一样Thread.stop,谨慎的方法是让“目标线程”轮询一个变量,该变量指示线程的所需状态(活动或挂起)。当所需的状态被挂起时,线程使用Object.wait. 当线程恢复时,目标线程使用 通知Object.notify

示例代码在相同的答案中给出,以帮助您实现这一目标。

于 2013-05-26T10:47:59.150 回答