繁体   English   中英

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

[英]Sending messages from many threads in Java

我需要从SomeObjectHandler实现handle()方法,该方法将SomeObject委托给某个外部系统(请参见下文)。 SomeObject具有正确的hashCode和equals方法。 方法handle(SomeObject someObject)可以从多个线程(例如10)中调用。 外部系统不能同时运行不等于someObject的操作,但是如果系统尝试同时运行相等的someObject的操作,则会中断。 我需要实现此类,以防止同时处理相等的someObject。 即使someObject相等,也应该处理所有这些对象。

现在,我在想我需要使用并发库中的Queue之类的东西,但是我不知道哪个。

UPD:我只需要使用标准的Java库。 并且如果有可能实现最大吞吐量。

我不确定100%是否能完全解决您的问题,但我认为有多种方法可以解决此问题。

1)正如您已经提到的,您可以使用队列来插入对象,并确保外部系统以同步方式处理对象,因为正如您所说的那样,外部系统无法同时处理相等的对象。

2)在发件人代码本身中处理。 我已经尝试了多次。 这是一个代码片段。 这种方法的优点是仅同步相等的对象。只需确保在finally块中也处理了移除部分。 对不起,如果代码不整洁。 我是这个新手:)

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可以在这里提供帮助。 它非常擅长处理数据流,尤其是涉及异步转换的数据流,并在需要时在后台进行您正在谈论的排队(无需通过同步修饰符进行阻塞!)。 为了解决您的问题,我将执行以下操作:

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

如果我正确理解了您的问题,则需要保证串行执行“相等对象”,而“不相等对象”可以并行处理。 实现此目的的一种方法是根据对象的某些确定性特性安排N个处理器并分散工作负荷。

在您的情况下,如果两个对象相等,则它们的哈希码必须相等,因此可使用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