Java 如何使线程/作业等待上一个作业完成,然后在收到通知后恢复它

Java 如何使线程/作业等待上一个作业完成,然后在收到通知后恢复它,java,multithreading,apache-camel,Java,Multithreading,Apache Camel,我有一个骆驼路线,它将对给定的ID执行更新 对于单个请求,一切正常,比如说,如果我有多个ID相同的请求,比如说10,那么我希望一次执行单个请求 或者使用相同的ID等待其他请求,同时如果我有其他ID的请求,可以不等待就处理,比如12 为此,我在我的Camel上下文“addRequestToPool”中创建了一个额外的路由,这将把所有到达Camel“updatecket”的请求路由到一个地方,并从那里逐个执行处理 我想实现如下内容: 当一个请求到达“synchronizeRequests”方法时,它

我有一个骆驼路线,它将对给定的ID执行更新

对于单个请求,一切正常,比如说,如果我有多个ID相同的请求,比如说10,那么我希望一次执行单个请求

或者使用相同的ID等待其他请求,同时如果我有其他ID的请求,可以不等待就处理,比如12

为此,我在我的Camel上下文“addRequestToPool”中创建了一个额外的路由,这将把所有到达Camel“updatecket”的请求路由到一个地方,并从那里逐个执行处理

我想实现如下内容:

当一个请求到达“synchronizeRequests”方法时,它应该检查docketId是否已经存在作业,如果已经存在,则让它等待旧流程完成(比如10)。如果没有这样的id(比如12),则继续处理

一旦旧流程完成,它应该告诉具有相同ID的其他正在等待的作业,其中一个可以从等待的位置恢复工作,以便发送响应

请求收集是从路由“addRequestToPool”完成的,一旦请求到来,它将为每个请求创建一个线程并调用同步方法。在同步方法“RequestSynchronization”中,我想对ID为的现有作业执行检查操作(如果存在),等待来自上一个if not返回响应的通知,然后继续处理

在结束时使用路由“removeRequestFromPool”完成作业后,将删除作业的当前id,并应通知组中的新作业(相同id)以继续

我想知道我应该如何实现上述场景或任何其他适当的方法(如果有的话)

下面是一段示例代码供参考

骆驼路线:

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行代码)
  • 即使处理组件因维护而停机,客户端仍可以发送更新请求
消息组是JMS代理功能(至少是ActiveMQ)。您将ID设置为
JMSXGroupID
,代理确保具有相同ID的所有消息都由同一消费者处理。如果您有5个消费者,并且收到10条具有相同ID的消息,则1个消费者完成所有工作。一旦有另一个ID的消息到达,另一个消费者就会并行处理它

如果您构建一个大型JMS组件来完成所有处理,或者构建多个组件来通过处理工作流中的多个队列传递消息,这取决于您。

我不熟悉apache camel,但仍然希望让您了解JDK的并发实用程序。请参见软件包和,最后是。当然,这些并不是唯一可用的参考资料。googleforjava并发实用程序。