我声明我读过有关线程的信息,但我从未使用过。所以我问你:)
我有两个线程:A
和B
,其中A
管理 GUI,并B
管理逻辑。
我会从A
.
然后在A
绘制 GUI 时,我会暂停它,等待B
到达 X 点进入运行方法。
当B
到达 X 点进入 run 方法时,我 pauseB
和 resume A
。
A
并B
共享一些变量来管理 GUI 和逻辑......
我可以做吗?如果是,如何?:)
我声明我读过有关线程的信息,但我从未使用过。所以我问你:)
我有两个线程:A
和B
,其中A
管理 GUI,并B
管理逻辑。
我会从A
.
然后在A
绘制 GUI 时,我会暂停它,等待B
到达 X 点进入运行方法。
当B
到达 X 点进入 run 方法时,我 pauseB
和 resume A
。
A
并B
共享一些变量来管理 GUI 和逻辑......
我可以做吗?如果是,如何?:)
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
}
}
};
(有关为什么在调用wait
and时我们需要如上所示进行同步的更多信息notifyAll
,请参阅有关该主题的 Java 教程。)
如果另一个 Thread 调用这个 Runnable 的pause()
方法,那么运行 runnable 的 Thread 将在它到达 while 循环的顶部时阻塞。
请注意,不可能在任意点暂停线程。您需要 Thread 定期检查它是否应该暂停并自行阻塞。
我希望您不需要暂停 GUI 线程。操作系统会处理这个问题,并且它需要准备好在用户做某事时做出响应。
另一种想法是确保共享变量在两个线程之间正确同步。我最近尝试回答与此相关的问题,请参见此处。
你可以使用一个CountDownLatch
. 当线程 A 必须等待时,线程 B 将调用countDownLatchInstance.await();
当 B 到达 X 点时将调用countDownLatchInstance.countDown()
;允许 A 继续其执行流程。
当你说
A 管理 GUI
希望你不要参考UI/Main Thread
,
这就是我让线程等待并通知为我工作的方式:
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);
}
}
然后,每当我按下按钮时,另一个线程就会唤醒,执行一轮并等待新的点击。
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();
不推荐使用暂停和恢复线程的 java 原语。请参阅此内容以了解如何实现所需的最佳效果 - http://docs.oracle.com/javase/7/docs/technotes/guides/concurrency/threadPrimitiveDeprecation.html 检查如何执行相当于暂停和恢复的操作
我应该使用什么来代替
Thread.suspend
andThread.resume
?与 一样
Thread.stop
,谨慎的方法是让“目标线程”轮询一个变量,该变量指示线程的所需状态(活动或挂起)。当所需的状态被挂起时,线程使用Object.wait
. 当线程恢复时,目标线程使用 通知Object.notify
。
示例代码在相同的答案中给出,以帮助您实现这一目标。