简体   繁体   English

从Java中的许多线程发送消息

[英]Sending messages from many threads in Java

I need to implement handle() method from SomeObjectHandler which delegates SomeObject to some outer system (see below). 我需要从SomeObjectHandler实现handle()方法,该方法将SomeObject委托给某个外部系统(请参见下文)。 SomeObject with correct hashCode and equals methods. SomeObject具有正确的hashCode和equals方法。 Method handle(SomeObject someObject) can called from many threads (10 for example). 方法handle(SomeObject someObject)可以从多个线程(例如10)中调用。 Outer system can operate not equals someObject at the same time just fine, but it will break if system is try to operate with equal someObject at the same time. 外部系统不能同时运行不等于someObject的操作,但是如果系统尝试同时运行相等的someObject的操作,则会中断。 I need to implement this class to prevent simultaneous processing of equal someObject. 我需要实现此类,以防止同时处理相等的someObject。 And even if some someObject are equal all of them should be processed. 即使someObject相等,也应该处理所有这些对象。

Now, I'm thinking that I need to use something like Queue from concurrent library, but I don't know which one. 现在,我在想我需要使用并发库中的Queue之类的东西,但是我不知道哪个。

UPD: I need to use only standard Java Libraries. UPD:我只需要使用标准的Java库。 And if it possible to achive maximum throughput. 并且如果有可能实现最大吞吐量。

I am not 100% sure if i got your question completely but i think there are multiple ways to approach this problem. 我不确定100%是否能完全解决您的问题,但我认为有多种方法可以解决此问题。

1) As you already mentioned you can use a queue for inserting objects and make sure the outer system processes the objects in synchronized manner because as you said your outer system is unable to process equal objects at the same time. 1)正如您已经提到的,您可以使用队列来插入对象,并确保外部系统以同步方式处理对象,因为正如您所说的那样,外部系统无法同时处理相等的对象。

2) Handle this in sender code itself. 2)在发件人代码本身中处理。 I have tried this multiple times. 我已经尝试了多次。 Here is a code snippet. 这是一个代码片段。 The pro of this approach is that it only synchronizes equal objects.Just make sure you handle the removal part in finally block as well. 这种方法的优点是仅同步相等的对象。只需确保在finally块中也处理了移除部分。 Sorry if the code is not tidy. 对不起,如果代码不整洁。 I am new at this :) 我是这个新手:)

Map<SomeObject,Integer> objMap=new ConcurrentHashMap<SomeObject,Integer>();

public void handle(SomeObject someObject) {
synchronized(this.class)
{
Integer count=objMap.get(someObject);  
if(count==null)
{
   count=0;
}
objMap.put(someObject,++count);
}

synchronized(objectMap.get(someObject)
{
  outerSystem.process(someObject);

  Integer count=objMap.get(someObject);  
  if(count>1)
 {
   objMap.put(someObject,--count);
 }
 else
 {
   objectMap.remove(someObject);
 }
}

}

RxJava can help out here. RxJava可以在这里提供帮助。 It's very good at handling streams of data especially involving asynchronous transformations and does the queueing you're talking about under the covers when required (without blocking via synchronized modifiers!). 它非常擅长处理数据流,尤其是涉及异步转换的数据流,并在需要时在后台进行您正在谈论的排队(无需通过同步修饰符进行阻塞!)。 To solve your problem I would do something like this: 为了解决您的问题,我将执行以下操作:

public class SomeHandler{

   private final OuterSystem outerSystem;

   private final PublishSubject<SomeObject> subject;

   public SomeHandler() {
       subject
          // handle calls from multiple threads (non-blocking)
          .serialized() 
          // buffer in memory if not keeping up       
          .onBackpressureBuffer() 
          // use equals/hashCode to order messages (the queues you referred to)
          .groupBy(x -> x)
          .flatMap(g -> 
              g.doOnNext(x -> outerSystem.process(x))
               // process groups in parallel
               .subscribeOn(Schedulers.computation()))
          // do something if an error occurs
          .doOnError(e -> e.printStackTrace())
          // start consuming data when arrives
          .subscribe();
   }

   public void handle(SomeObject someObject) {
      subject.doOnNext(someObject);
   }
}

If I understand your problem correctly you need to guarantee serial execution of "equal objects", while "unequal objects" can be processed in parallell. 如果我正确理解了您的问题,则需要保证串行执行“相等对象”,而“不相等对象”可以并行处理。 One way to achieve this is to arrange N processors and spread the workload according to some deterministic characteristic of the objects. 实现此目的的一种方法是根据对象的某些确定性特性安排N个处理器并分散工作负荷。

In your case, if two objects are equal, their hash codes must be equal, so the hasCode() modulo N could be used to spread the load over N Executors, where each Executor contains a single thread only: 在您的情况下,如果两个对象相等,则它们的哈希码必须相等,因此可使用hasCode() modulo N来将负载分散到N个执行器上,其中每个执行器仅包含一个线程:

public class SomeHandler {
   static int N = ...;
   // Each executor is an Executors.newSingleThreadScheduledExecutor()
   Executor[N] executors = ....;
   OuterSystem system;

   public void handle(SomeObject so) {
       executors[so.hashCode() % N].execute(() -> system.process(so));
   }
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM