1

我正在使用以下自旋锁方法:

while(!hasPerformedAction()){
    //wait for the user to perform the action
    //can add timer here too
}

setHasPerformedAction(false);

return getActionPerfomed();

这基本上等待用户执行一个操作,然后返回它。目前有些东西在继续之前要求用户回答,这就是我等到收到输入的原因。但是我想知道这是否效率低下,如果我们等待一段时间(即 <= 30 秒)会减慢运行此应用程序的电脑的速度。是否有任何其他使用这种方法的替代方法,即锁、信号量,如果是的话,语法是什么?

谢谢,

阿里

4

5 回答 5

9

事实上,这不仅效率低下,甚至不能保证工作,因为在您显示的代码中没有“发生在之前”的边缘。要创建先发生边缘,您需要执行以下操作之一:

  1. 访问 volatile 变量
  2. 在共享资源上同步
  3. 使用并发 utils 锁。

正如另一条评论中提到的,最简单的解决方案就是确保您的标志是一个 volatile 变量,并在您的循环中简单地抛出一个短暂的睡眠。

但是,最好的办法是在共享变量上同步/等待/通知。

您需要阅读的方法是waitnotify。有关如何使用它们的更好描述,请阅读本文。示例代码片段如下所示;

线程 1

Object shared = new Object();
startThread2(shared);
synchronized (shared) {
  while (taskNotDone())
    shared.wait();
}

线程 2

// shared was saved at the start of the thread
// do some stuff
markTaskAsDone();
synchronized (shared) {
  shared.notify();
}
于 2010-01-31T21:09:23.923 回答
2

你写的东西叫做忙循环,你不应该这样做。

您可能想继续这样做,但至少要睡一会儿,以免忙于循环,这仍然不是那么好:

while( !hasPerformedAction() ) {
    (sleep a bit here)
}

另一种方法是将用户操作排入阻塞队列:然后您可以简单地使用queue.take并且队列实现将为您解决问题。

另一种方法是使用回调来通知用户操作。

于 2010-01-31T21:09:29.930 回答
2

java教程有一个很好的关于java并发的课程:

http://java.sun.com/docs/books/tutorial/essential/concurrency/

如果您要从另一个线程修改 UI,您需要记住:

SwingUtils.invokeLater(actionToInvoke);
于 2010-01-31T21:09:43.317 回答
1

您的标签中有一个gui,所以我假设该操作是在 GUI 中完成的。

做这种事情的“推荐”方法是让主线程让自己进入睡眠状态(可能使用),并且一旦执行了操作wait(),GUI 操作就会将其重新唤醒。notify()

于 2010-01-31T21:07:13.943 回答
1

java.util.concurrent.locks. 看看类LockSupport

问候迈克

于 2010-01-31T21:08:21.197 回答