简体   繁体   中英

Sending messages from many threads in Java

I need to implement handle() method from SomeObjectHandler which delegates SomeObject to some outer system (see below). SomeObject with correct hashCode and equals methods. Method handle(SomeObject someObject) can called from many threads (10 for example). 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. I need to implement this class to prevent simultaneous processing of equal someObject. And even if some someObject are equal all of them should be processed.

Now, I'm thinking that I need to use something like Queue from concurrent library, but I don't know which one.

UPD: I need to use only standard Java Libraries. 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.

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.

2) Handle this in sender code itself. 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. 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. 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.

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:

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));
   }
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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