簡體   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