我有点问题。我有一个java应用程序,当它启动时,它需要制作大约六个或七个线程,等待某种事件发生(即用户按下按钮)。我如何制作这些线程的一个例子如下。问题是,我打开我的任务管理器只看到我的四个cpu核心都是100%(从大约20开始),一旦我关闭我的应用程序,一切都恢复正常。我仍然是多线程的新手,我知道我在这里犯了某种并发罪,但我很感激有关如何纠正这种情况的任何见解。
new Thread (new Runnable() { public void run()
{
while (true)
if (doSomeFunction)
{
myFunction();
doSomeFunction = false;
}
} } ).start();
// Somewhere else in the code
doSomeFunction = true;
我在想也许等一下,通知将是正确的做法吗?
编辑:为了澄清,这与为摇摆组件供电无关。相反,这会根据脚本执行事件,我不希望某些脚本函数被阻止,而是在后台完成任务时立即返回。
答案 0 :(得分:5)
这里有两个可能的答案。
首先,您正在等待在Swing应用程序(或类似)中按下按钮。如果是这样,线程不是答案。你应该只使用一个动作监听器:
JButton button = ...
button.addActionListener(new ActionListener() {
void actionPerformed(ActionEvent e) {
// do stuff
}
});
在Swing应用程序中使用线程时需要非常小心。这是因为只有一个线程(称为事件调度线程或EDT)是唯一允许进行UI更新的线程。所有事件处理程序都在EDT中发生。因此,当代码在EDT上运行时,不会发生UI更新(移动/关闭窗口,按下按钮等),因此EDT代码应该是短暂的。
更普遍的问题可以通过多种方式解决,这些方式依赖于比提供的信息更多的信息。
首先,回答你的问题:你的CPU使用率是100%,因为线程不断检查值并在无限循环中调用函数。
你应该使用Java 5+并发模型,它看起来更像是这样:
ExecutorService threadPool = Executors.newFixedThreadPool(10); // or whatever
threadPool.submit(new Runnable() {
public void run() {
// do stuff
}
});
关于如何进行线程间通信,这就是它变得棘手的地方。你正在共享一个原始变量,这是一个非常糟糕的主意。
最简单的习惯是使用wait-notify:
final Object someObject = ...
ExecutorService threadPool = Executors.newFixedThreadPool(10); // or whatever
threadPool.submit(new Runnable() {
public void run() {
synchronized (someObject) {
someObject.wait();
}
// do stuff
}
});
...
synchronized (someObject) {
someObject.notify(); // wakes ONE waiting thread
}
synchronized
互斥锁确实非常重要。
但Java 5为此添加了一大堆替代品。我建议购买Java Concurrency in Practice并阅读封面以封面。
答案 1 :(得分:4)
如果您试图控制所有线程何时开始工作,那么引入Java 5的CountDownLatch可能是一个简单的解决方案:
public void static main(String[] args) {
final CountDownLatch signalToDoSomeFunction = new CountDownLatch(1);
new Thread(new Runnable() {
public void run() {
// wait until the latch is "counted down"
signalToDoSomeFunction.await();
myFunction();
});
// create other threads similarly
// all thread created but waiting, now ready to start work
signalToDoSomeFunction.countDown();
}
这消除了inifinte循环。 CountDownLatch隐藏了一个更好的接口后面的Object.wait()和Object.notify()调用。
答案 2 :(得分:3)
您正在做的事情称为Busy waiting。 快速而肮脏的修复方法是将Thread.sleep(1)添加到代码中。这应该足以降低cpu利用率。
然而,正确的解决方案是使用适当的同步技术,例如一个Semaphore
答案 3 :(得分:1)
在while循环结束时,你应该有Thread.sleep(250)
之类的东西。这导致当前线程休眠250毫秒,因此它不会烧掉CPU而只是循环。