【问题标题】:How to enable thread in java to receive notifications from 2 threads?如何在java中启用线程以接收来自2个线程的通知?
【发布时间】:2017-02-25 07:50:07
【问题描述】:

我正在编写具有多个线程的程序。 在那个程序中,我经常使用 wait 和 notify 让一个线程等待,直到另一个线程唤醒它。

在我的想象项目中,假设我有 3 个线程:m、a 和 b。 m是主要的。 m线程启动一个线程并启动b线程。 m 线程应该等待某个线程完成其工作(不要死)。如果 a 完成,则 m 应该被唤醒并做一件事。如果 b 完成,它应该被唤醒并做另一件事。

我可以在 m 中使用这样的东西:

synchronized(a)
{
    a.wait();
}

和类似这样的东西:

synchronized(this)
{
    notify();
}

如果我想等待 b,同样的事情也会发生。米:

synchronized(b)
{
    b.wait();
}

在乙:

synchronized(this)
{
    notify();
}

但是,如果我想同时等待它们,我需要这样的代码:

synchronized(a, b)
{
    a,b.wait();
}

当然,这在 java 中是不支持的。

当然,我可以将 main 置于 sleep(32) 或类似的状态,并将完成标志放在 a 和 b 中,当 m 醒来时,它会检查标志,并知道其中一个完成了。 但是通过等待通知方法,我想避免不断检查 a 和 b 中的那些完成标志。

那么,什么是解决方案? 有什么办法,除了不断检查标志外,我可以发现 a 或 b 从 m 完成(没有死)?

【问题讨论】:

  • 您的解释有点混乱,m 是应该等待 both ab 完成还是要返回 m每次ab 完成他们的工作,b 有一个延续或完全不同的东西?
  • 是的,m 应该等待 a 或 b。 a 和 b 正在做一些多阶段的工作。每当 a 完成一个阶段时,我希望它通知 m。并且每当 b 完成一个阶段时,我也希望它通知 m 。当a通知m时,m应该写“a通知我”,当b通知m时,m应该写“b通知我”。

标签: java multithreading java-threads


【解决方案1】:

要让主线程 m 在任何子线程(在本例中为 ab)完成工作后做出反应,有几个选项。

在最简单的情况下,m 应该将相关线程保存在一个列表中,并在两个循环中首先启动其他线程,然后在另一个循环中等待线程完成。所以,你需要有这样的东西:

public class MainThread {
    public void run() {
        List<Thread> threads = Arrays.asList(
            new Thread(() -> react(this)),
            new Thread(() -> react(this)),
        );
        // start all threads first to avoid deadlock
        threads.forEach(Thread::start);
        // wait for all threads to finish in order
        threads.forEach(Thread::join);
        // here you can do whatever post steps you want
    }
    public void react(Thread t) {
        System.out.print("MainThread called by " + t);
    }
}

还有很多其他解决方案可以实现这样的目标:

等等等等。

【讨论】:

    【解决方案2】:

    您可以对共享对象进行同步(等待、通知)。也许在 m 上?!

    【讨论】:

      【解决方案3】:

      不要让mab 完成时做事,而是让ab 做正确的事。

      我建议使用CompletableFuture

      CompletableFuture.runAsync( <thread A> )
           .thenRun( <stuff that should be done after A completes> );
      

      【讨论】:

      • 如果没有额外的上下文,“正确的事情”还不如让主线程继续做它正在做的事情。
      • 是的,我建议在这里重写以简化问题,而不是尝试使用与此类问题不匹配的习语。
      • 这可能不会简化问题。如前所述,我们需要更多上下文 - 您建议的习语删除了实际处理并行执行的整个 fork/join 模型的“join”部分的概念。
      【解决方案4】:

      在您的上下文中使用 CompletableFuture 将达到目的。

      【讨论】:

        猜你喜欢
        • 2015-05-18
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2017-09-03
        • 1970-01-01
        • 2020-04-16
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多