![](/img/trans.png)
[英]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.