等待所有线程在Spring Integration中完成

时间:2012-01-19 10:44:28

标签: java multithreading spring spring-integration

我有一个自我执行的jar程序,它在很大程度上依赖于Spring Integration。我遇到的问题是程序在其他Spring bean完成之前终止

以下是我正在使用的代码的简化版本,如果需要,我可以提供更多代码/配置。入口点是一个main()方法,它引导Spring并启动导入过程:

public static void main(String[] args) {
    ctx = new ClassPathXmlApplicationContext("flow.xml");
    DataImporter importer = (DataImporter)ctx.getBean("MyImporterBean");
    try {
        importer.startImport();
    } catch (Exception e) {
        e.printStackTrace();
    } finally {
        ctx.close();
    }
}

DataImporter包含一个简单的循环,可以将消息发送到Spring Integration网关。这为流程提供了一种主动的“推送”方法,而不是轮询数据的常用方法。这是我的问题所在:

public void startImport() throws Exception {
    for (Item item : items) {
        gatewayBean.publish(item);
        Thread.sleep(200); // Yield period
    }
}

为了完整起见,流XML看起来像这样:

<gateway default-request-channel="inChannel" service-interface="GatewayBean" />

<splitter input-channel="inChannel" output-channel="splitChannel" />

<payload-type-router input-channel="splitChannel">
    <mapping type="Item" channel="itemChannel" />
    <mapping type="SomeOtherItem" channel="anotherChannel" />
</payload-type-router>

<outbound-channel-adapter channel="itemChannel" ref="DAOBean" method="persist" />

流程有效地启动和处理项目,但是一旦startImport()循环结束,主线程终止并立即拆除所有Spring Integration线程。这会导致竞争条件,当程序终止时,最后(n)项未完全处理。

我有一个想法是保持我正在处理的项目的引用计数,但事实证明这非常复杂,因为流程经常将消息拆分/路由到多个服务激活器 - 这意味着很难确定是否每个项目已“完成”。

我认为我需要的是检查没有Spring bean仍在执行的方法,或者标记发送到网关的所有项目在终止之前已经完全处理。

我的问题是,我怎么可能去做其中任何一项,或者是否有更好的方法解决我没想过的问题?

2 个答案:

答案 0 :(得分:9)

您这里没有使用请求 - 响应模式。

outbound-channel-adapter是一个即发即弃操作,如果你想等待响应,你应该使用一个等待响应的出站网关,并将响应连接到原来的网关,然后在java sendAndReceive中刚发布。

答案 1 :(得分:3)

如果你可以得到一个Item来确定它是否仍然需要(processingFinished()或者在后端阶段执行类似的东西),你可以注册所有Item个在中央机关,它跟踪未完成Item的数量,并有效地确定终止条件。

如果这种方法可行,您甚至可以考虑将项目打包到FutureTask - 对象中,或者使用java.util.concurrent中的类似概念。

编辑:第二个想法:

您是否考虑过让频道变得更聪明?一旦发送者不再发送任何数据,发送者就会关闭该频道。在这种情况下,worker-bean不必是deamon线程,但可以根据封闭和空的输入通道确定它们的终止条件。

相关问题