我正在查看当前的帖子: How to create a thread that waits for a boolean variable to become true?
每个人似乎都彼此不同意,没有人能够充分发挥自己,所以我将以最简单的方式呈现这一点。这是我今天的代码。
boolean connecting = false;
public static void main(String[] args) {
initUI();
while(true) {
if(connecting) {
connecting = false;
doSomething();
}
};
}
initUI()是一个启动用户界面的方法。当用户单击该类中名为“Connect”的按钮时,它将调用它的动作侦听器并将布尔值“连接”设置为“true”。当它进入if区域时,它会将布尔值重置为“false”并运行我想要的代码。
但这有效......它使用了太多的CPU。
如果我直接将按钮动作侦听器设置为doSomething()方法,则程序会阻塞(并且应该),因为动作侦听器方法需要完成才能重置按钮。然而,doSomething()有循环(它是一个聊天程序),所以它不会返回到原始的(在代码中显示),直到他断开连接。
所以我的问题是,无论如何要“等待”布尔值更改为true。例如听众?
答案:感谢Joni我实施了一个主题。
按钮actionListener现在包括:
(new connectThread()).start();
我的帖子看起来像这样:
public class connectThread extends Thread {
public void run() {
ui.btn.setEnabled(false);
doSomething();
ui.btn.setEnabled(true);
}
}
关于问题标题,等待布尔值改变,因为另一个人解释了可以设置事件监听器。
答案 0 :(得分:2)
返回事件监听器调用doSomething()
的代码,但只需更改一次:启动运行doSomething()
的新线程,而不是直接调用它。您可以在the Java Tutorial: Simple Background Tasks中找到有关如何执行此操作的完整示例。 SwingWorker API documentation也有一个例子。
答案 1 :(得分:2)
你走错了路 - “忙着等待”,因为你在这里做的几乎总是错误的想法,因为它不必要地耗费CPU时间。
根据我的理解,您希望在不锁定UI线程的情况下按下按钮。正如Joni建议的那样,没有必要让线程在此之前等待 - 只要按下按钮就启动它。如果要确保一次只处理一个按钮,则可以使用具有单个线程的线程池(请参阅SingleThreadExecutor)。
我还想在你的示例代码中指出一个重要的错误:connecting
需要变为volatile来告诉编译器该值可能会从另一个线程发生变化。实际上,无法保证您的工作线程会看到值更改,因此即使您在另一个线程中将connecting
设置为true,它也可以无限循环。
答案 2 :(得分:2)
所以我的问题是,无论如何要“等待”布尔值更改为true。
使用裸boolean
变量无法(高效且响应性地)执行此操作。 sleep
/测试循环是一个糟糕的解决方案,因为它既昂贵又无响应。如果睡眠间隔很小,你会浪费CPU,如果你把它放大,你的应用程序需要(相对)很长的时间注意状态改变。
但如果通过方法(例如setter)更新boolean
,那么您可以将setter编码为:
notify
在互斥锁中等待的其他线程;例如https://stackoverflow.com/a/12884570/139985或
调用一些“事件监听器”回调。
答案 3 :(得分:0)
你可以放入Thread.sleep(100);在循环中,所以它不是那样的紧密循环,它可以轻松地冻结其余的线程。
您还可以使用等待/通知机制。只需要一个共享的Object,signaller ......有“while(true)”调用“signaller.wait()”,然后,在你的另一个线程设置了标志(它可能不需要)之后,它就可以调用“signaller”。 notifyAll()“将让其他线程运行其下一次迭代,并看到该标志已设置。
答案 4 :(得分:0)
在您的侦听器中,您可以在新线程中运行doSomething()
,而不是设置标志。在下面的示例中,ThreadTest
实际上是您当前拥有侦听器方法的类(我称之为onClick()
)。
public class ThreadTest {
private ExecutorService service;
public ThreadTest() {
service = Executors.newFixedThreadPool(10);
}
// Button click listener.
public void onClick() {
service.submit(new Runnable() {
@Override
public void run() {
doSomething();
}
});
}
public void doSomething() {}
}