[英]Java email sending queue - fixed number of threads sending as many messages as are available
[英]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.