Java 如何使线程/作业等待上一个作业完成,然后在收到通知后恢复它
我有一个骆驼路线,它将对给定的ID执行更新 对于单个请求,一切正常,比如说,如果我有多个ID相同的请求,比如说10,那么我希望一次执行单个请求 或者使用相同的ID等待其他请求,同时如果我有其他ID的请求,可以不等待就处理,比如12 为此,我在我的Camel上下文“addRequestToPool”中创建了一个额外的路由,这将把所有到达Camel“updatecket”的请求路由到一个地方,并从那里逐个执行处理 我想实现如下内容: 当一个请求到达“synchronizeRequests”方法时,它应该检查docketId是否已经存在作业,如果已经存在,则让它等待旧流程完成(比如10)。如果没有这样的id(比如12),则继续处理 一旦旧流程完成,它应该告诉具有相同ID的其他正在等待的作业,其中一个可以从等待的位置恢复工作,以便发送响应 请求收集是从路由“addRequestToPool”完成的,一旦请求到来,它将为每个请求创建一个线程并调用同步方法。在同步方法“RequestSynchronization”中,我想对ID为的现有作业执行检查操作(如果存在),等待来自上一个if not返回响应的通知,然后继续处理 在结束时使用路由“removeRequestFromPool”完成作业后,将删除作业的当前id,并应通知组中的新作业(相同id)以继续 我想知道我应该如何实现上述场景或任何其他适当的方法(如果有的话) 下面是一段示例代码供参考 骆驼路线:Java 如何使线程/作业等待上一个作业完成,然后在收到通知后恢复它,java,multithreading,apache-camel,Java,Multithreading,Apache Camel,我有一个骆驼路线,它将对给定的ID执行更新 对于单个请求,一切正常,比如说,如果我有多个ID相同的请求,比如说10,那么我希望一次执行单个请求 或者使用相同的ID等待其他请求,同时如果我有其他ID的请求,可以不等待就处理,比如12 为此,我在我的Camel上下文“addRequestToPool”中创建了一个额外的路由,这将把所有到达Camel“updatecket”的请求路由到一个地方,并从那里逐个执行处理 我想实现如下内容: 当一个请求到达“synchronizeRequests”方法时,它
from("direct:updateTicket")
.to("direct:addRequestToPool")
.to("direct:getDetailForTicket")
.to("direct:updateDetailForTroubleTicket")
.to("direct:getDetailForTicket")
.to("direct:removeRequestFromPool")
.to("direct:endRoute");
API调用:
public class TicketRequestManagement {
public SimpleActionResponse addRequestToPool(int docketNo) throws InterruptedException {
SimpleActionResponse response = new SimpleActionResponse();
RequestSynchronization requestSynchronization = new RequestSynchronization(docketNo);
Thread thread = new Thread(requestSynchronization);
thread.start();
thread.join();
return response;
}
}
同步方法:
public class RequestSynchronization implements Runnable {
private static Logger logger = Logger.getLogger(RequestSynchronization.class);
private int docketNo;
public RequestSynchronization(int docketNo) {
super();
this.docketNo = docketNo;
}
@Override
public void run() {
synchronizeRequests(docketNo);
}
public synchronized static void synchronizeRequests(int docketNo) {
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
我正在考虑将docketId添加到静态数据结构(Set)中,并检查是否存在Id等待(我应该如何执行此等待?)一旦流程完成,从集合中删除Id并通知等待流程从那里恢复(我应该如何执行此通知到同一Id?)
如果需要澄清,请告诉我
PS:我不是在寻找睡眠,这只是为了执行同步测试
提前谢谢。首先,不要手动启动
线程
,这就是执行器服务
的用途
其次,我建议您在Map
中维护已启动的同步,这样您就可以检查该id是否已经在运行
一份草稿就可以了
class TicketRequestService {
private Map<Integer, Future<?>> runningRequests = new ConcurrentHashMap<>();
ExecutorService executor = Executors.newCachedThreadPool();
public void synchronizeRequest(int docketId) {
// get the running Future if present, otherwise...
Future<?> future = runningRequests.computeIfAbsent(docketId,
// ...create a new one
id-> executor.submit(() -> {
RequestSynchronization.synchronizeRequests(id));
// remove future from map after sync is finished
runningRequests.remove(docketId);
});
future.get(); // wait until finished; this throws Exceptions, you need to handle them
return new SimpleActionResponse();
}
}
class TicketRequestService{
private Map future=runningRequests.computeIfAbsent(docketId,
//…创建一个新的
id->executor.submit(()->{
RequestSynchronization.synchronizeRequests(id));
//同步完成后从映射中删除future
运行请求。删除(docketId);
});
future.get();//等待完成;这会抛出异常,您需要处理它们
返回新的SimpleActionResponse();
}
}
我的建议:异步化。例如,使用JMS(不是直接的,而是with)来解耦请求和对它们的处理。通过这种方式,您可以简单地通过消费者数量控制整个线程
在你的情况下,这将是
- addRequestToPool将请求放在JMS队列上
- JMS使用者使用队列中的请求并对其进行处理
- 使用同步具有相同ID的请求
- 使用消费者计数确保并行处理其他ID并按比例放大(为线程编写0行代码)
- 即使处理组件因维护而停机,客户端仍可以发送更新请求
JMSXGroupID
,代理确保具有相同ID的所有消息都由同一消费者处理。如果您有5个消费者,并且收到10条具有相同ID的消息,则1个消费者完成所有工作。一旦有另一个ID的消息到达,另一个消费者就会并行处理它
如果您构建一个大型JMS组件来完成所有处理,或者构建多个组件来通过处理工作流中的多个队列传递消息,这取决于您。我不熟悉apache camel,但仍然希望让您了解JDK的并发实用程序。请参见软件包和,最后是。当然,这些并不是唯一可用的参考资料。googleforjava并发实用程序。