【问题标题】:Coordinate threads without wait/notify if possible如果可能,无需等待/通知即可协调线程
【发布时间】:2013-02-26 13:22:58
【问题描述】:

除了wait/notify,还有更简洁的线程间事件通知方式吗?
例如。如果我想让Thread X 通知ThreadY 发生了某些事情,在并发包中是否有比在wait/notify 之上构建它更好的构造?
我的要求很简单: ThreadB 期望事件发生。 ThreadA 负责检测此类更改。当发生变化时ThreadA 通知ThreadB

更新:
我需要执行 Observer/Observable 模式,但我希望 observable 在通过循环通知观察者时尽可能少地阻塞。
IE。观察者将是单独的线程,并且可观察到的火变化将“通知”它们以尽可能少地阻塞

【问题讨论】:

  • 您能否详细说明您的要求?你在java.util.concurrent 中看到了什么(例如CyclicBarrierCountdownLatch?你需要传递信息,还是只传递通知本身?
  • 如何更好? java有信号量,IIRC。
  • @JonSkeet:请参阅更新。您提到的那些构造是关于一起启动线程等,对吗?
  • @MartinJames:我的意思是如果有比等待/通知更高级别的构造,我想使用它
  • 没有什么比为此等待/通知更好的了。去做就对了。很简单。

标签: java multithreading events concurrency java.util.concurrent


【解决方案1】:

不幸的是,您的要求仍然含糊不清。您可以将三个主要的并发原语用于更高级别的通知,然后是等待/通知和等待/信号。

您可以设置一个等待线程完成的屏障,一个等待来自另一个线程的消息的屏障,或者您可以设置一个等待多个线程处理事件的屏障。

您可以使用CyclicBarrierCountdownLatchPhaser

对于第二个,您可以使用任何 BlockingQueue,无论是 LinkedBlockingQueueArrayBlockingQueueSynchronousQueue 还是 TransferQueue

最后你可以使用ExecutorService + Future

下一个问题:

究竟什么是事件以及正在发生什么变化?这很重要,如果某个字段正在更改,您可以使用 SettableFuture 支持您的字段/事件更新

编辑:

您能否添加一个新库。看来Akka 很适合你。

【讨论】:

  • 你写的第二个:a barrier that waits for a message from another thread 似乎正是我所需要的。但是如何使用队列?我这里不需要队列。另外我不确定还要写什么更清楚
  • @Jim 当你说update to notify 时,被通知的线程是否需要更新线程的结果,还是只需要通知它可以开始某些事情。
【解决方案2】:

您可以使用ExecutorService。它是从Executor 扩展而来的,它提供了管理终止的方法和可以产生Future 以跟踪一个或多个异步任务的进度的方法。在某种情况下使用非常简单就像你描述的Inter Thread Communication

【讨论】:

  • @Jim 如果我没听错你说的是这个设计en.wikipedia.org/wiki/Observer_pattern
  • 没错。但是我需要在单独的线程中完成通知,这样observable才不会被阻塞。只需通知并返回
【解决方案3】:

不要写等待/通知。 使用 java.concurrent 工具。 http://docs.oracle.com/javase/1.5.0/docs/api/java/util/concurrent/package-summary.html

例如,如果未绑定队列适合您的要求,则使用 ConcurrentLinkedQueue: http://docs.oracle.com/javase/1.5.0/docs/api/java/util/concurrent/ConcurrentLinkedQueue.html

顺便说一句,最好的选择是通过使用期货和演员来完全避免手动管理线程。

【讨论】:

  • ConcurrentLinkedQueue 真的不是这里最好用的队列。它是线程安全的,但没有等待语义。
  • 但是我不需要队列。只是一个通知机制
【解决方案4】:

java.util.concurrent.locks 包类 Lock、Condition 和其他类可以更好地控制线程协调。

【讨论】:

    【解决方案5】:

    如果您不想阻止观察者(因为他们正忙于其他任务),那么您需要实现某种轮询机制。你不能只是神奇地调用另一个未被阻塞的线程中的方法,因为另一个线程有自己的顺序逻辑。

    最简单的轮询解决方案是将 volatile 变量设置为特殊值,并定期从观察者线程检查该变量。

    【讨论】:

      【解决方案6】:

      如果您不想引入任何复杂的数据结构而只是通知线程,那么您还可以查看中断线程。消费者线程并循环运行,当被中断时,它们执行处理,然后再次退出/循环运行。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2012-07-12
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2012-11-18
        • 2020-04-18
        • 2015-02-19
        • 2015-08-25
        相关资源
        最近更新 更多