让线程等待

时间:2010-09-28 16:31:41

标签: java multithreading concurrency

我有点问题。我有一个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;

我在想也许等一下,通知将是正确的做法吗?

编辑:为了澄清,这与为摇摆组件供电无关。相反,这会根据脚本执行事件,我不希望某些脚本函数被阻止,而是在后台完成任务时立即返回。

4 个答案:

答案 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而只是循环。