阻止一个线程,直到它从其他线程(java)获得特定信号

阻止一个线程,直到它从其他线程(java)获得特定信号,java,multithreading,synchronize,Java,Multithreading,Synchronize,我有一个java服务器应用程序,通过套接字与客户机通信。每个客户端请求都在一个新线程中处理。但是对于一些请求,我需要同步两个客户端 例如: 客户端A向服务器S发送请求 S上的线程S1接受A的请求 S1将此请求通知客户端B(通过GoogleCloudMessaging) S1现在应该阻塞了 客户端B从S接收信息并向S发送请求 S上的线程S2接受B的请求 S1现在应该被释放,并从S2获得消息 S1将答案发送给客户端A 我知道锁条件机制,但这在这里不起作用,因为我不知道创建线程时的条件。我需要像这

我有一个java服务器应用程序,通过套接字与客户机通信。每个客户端请求都在一个新线程中处理。但是对于一些请求,我需要同步两个客户端

例如:

  • 客户端A向服务器S发送请求
  • S上的线程S1接受A的请求
  • S1将此请求通知客户端B(通过GoogleCloudMessaging)
  • S1现在应该阻塞了
  • 客户端B从S接收信息并向S发送请求
  • S上的线程S2接受B的请求
  • S1现在应该被释放,并从S2获得消息
  • S1将答案发送给客户端A
我知道锁条件机制,但这在这里不起作用,因为我不知道创建线程时的条件。我需要像这样的东西:

// Pseudo Code
// on the S1 Thread, first argument beeing a signal ID, second a timeout
s1.waitForSignal("clientB", 10000);
// and on the S2 Thread to continue S1
SignalSender.send("clientB");

在Java中有这样的功能吗?我的问题还有其他解决方案吗?

您的问题似乎是您没有一个可以调用
wait
/
notify
的共享引用(更不用说您可以使用的共享锁定条件)

首先,这两个线程之间已经有了共享的东西:即,在您的例子中,字符串
“ClientB”
。如果您有这个功能,您所需要做的就是将该字符串映射到两个类都可以访问的地方的单个引用

最简单的实现是在某个地方保存一个静态映射字段,然后以某种方式用监视器对象填充它:

public final class Monitors {

    private Monitors() {}

    private static final Map<String, Object> monitors = new HashMap<String, Object>();

    static { monitors.put("ClientB", new Object()); }

    public static Object get(String key) { return monitors.get(key); }

}
公共最终类监控器{
专用监视器(){}
私有静态最终映射监视器=新HashMap();
静态{monitors.put(“ClientB”,new Object());}
公共静态对象get(字符串键){return monitors.get(键);}
}

当然,您可能希望编写一个适当的服务来管理此映射,并可能在内部使用锁和条件。另外,一个好主意是将等待和信令功能封装在服务本身中,然后像这样使用:
monitorService.waitForSignalsFrom(“ClientB”)

是的,有等待和通知方法。尝试使用它们。不,不要使用等待和通知。它们是过去的遗迹,新代码不应该使用它。使用
java.util.concurrent
中适当的同步辅助工具,例如
CountDownLatch
。谢谢,我喜欢比萨饼示例。但是使用wait¬ify,我仍然需要两个线程中的waiting对象的实例,不是吗?因为我不知道创建时哪个线程必须等待或通知哪个线程。我在解析来自套接字的消息时(或者在获取SSLSession对象时)首先知道这一点。@user2564801看起来您正在走一条潜在的死锁路径。考虑潜在的情况,其中线程的S线程中的所有线程都是客户端等待的,以便等待B的连接。B无法连接,因为线程池中没有剩余的线程可以接受连接,而A在收到B的消息之前将永远不会继续。请确保在链的某个位置有某种超时逻辑(即使Tomcat为您处理超时)。倒计时闩锁似乎也很好。但是我仍然需要以某种方式在运行时将CountDownLatch对象传递给我的另一个线程。我该怎么做?某种全局同步HashMap?那么您的答案实际上是您认为OP不应该做什么的声明不是真的:我指出了一个解决方案;实际的实现太简单了,不能这样使用。但你是对的,最后的警告有点搞砸了:我来编辑:)我只是让你很难受。这个问题似乎没有一个非常干净的解决方案(可以用一个非常简单的答案来回答),所以它可能是这样工作的:?我会通过CountDownLatch()同步线程,但在全局同步映射对象中处理CountDownLatch对象?假设您将该功能封装在共享组件(某些服务)中——只是为了让这听起来更好。当然,接口和实现都有改进的余地:对于接口,我宁愿不返回CDL,而是在内部对其执行操作。为了实现,您应该考虑使用<代码>并发映射< /代码>…