【问题标题】:Spring Task Executor created extra threads in JUNITSpring Task Executor 在 JUNIT 中创建了额外的线程
【发布时间】:2016-02-18 11:48:38
【问题描述】:

我的 spring-config.xml 中有简单的任务执行器,并附加了几个链

      <channel id="inputChannel" />
    <task:executor id="threadPoolExecutor" pool-size="2" />
    <publish-subscribe-channel id="multiCastChannel"
        task-executor="threadPoolExecutor" />

    <chain input-channel="inputChannel"
        output-channel="multiCastChannel">
        <json-to-object-transformer
            type="com.company.integration.domain.DomainObject" />
        <service-activator ref="validator"
            method="validate" />
</chain>

<chain input-channel="multiCastChannel"
        output-channel="inventoryAdjustmentOutputChannelOne">
        <service-activator ref="adapterOne"
            method="buildOutputMessageOne" />
</chain>
<chain input-channel="multiCastChannel"
        output-channel="inventoryAdjustmentOutputChannelTwo">
        <service-activator ref="adapterTwo"
            method="buildOutputMessageTwo" />
</chain>

当一条消息发布到“inputChannel”并经过处理并发送到“multuCastChannel”时,会创建两个没有问题的线程

threadPoolExecutor-1 threadPoolExecutor-2

并且这两个只在每个输入消息中创建一次,这很好。 但是,当我尝试使用 JUnit 进行相同测试时……每个“multiCastChannel”链都执行了两次……意味着我的服务激活器(adapterOne、adapterTwo)在链中调用了两次 每条链......这是有线的......

知道为什么 JUnit 有这种行为吗?

下面是Junit的一段代码

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = { "classpath:configuration/spring-config.xml"})
@FixMethodOrder(MethodSorters.NAME_ASCENDING)
@PropertySource("classpath:application.properties")
@SuppressWarnings("unchecked")
@WebAppConfiguration
@DirtiesContext(classMode = DirtiesContext.ClassMode.AFTER_EACH_TEST_METHOD)
public class InventoryAdjustmentMessageTest {


    @Autowired
    private DirectChannel inputChannel;


    @Test
    public void testTaskShed()
            throws IOException, InterruptedException, JMSException {
        String validInput = setup("valid-message.txt");
        Message<String> inputMessage = TextMessageUtil.createNewGenericMessage(validInput);
        inputChannel.send(inputMessage);
        Thread.sleep(5000);

}

Spring 集成版本:4.1.6

添加应用配置信息:

@Import({ HarnessConfiguration.class, LocalConfiguration.class, MongoDbConfiguration.class, WebConfiguration.class,
        WebsphereMQJMSConfiguration.class })
@Configuration
@EnableWebMvc
@ComponentScan(basePackages = { "com.abc.inventory.adjustment.integration.service",
        "com.abc.inventory.adjustment.integration.domain" }, useDefaultFilters = false, excludeFilters = {
                @ComponentScan.Filter(type = FilterType.ASSIGNABLE_TYPE, value = ApplicationConfiguration.class) }, includeFilters = {
                        @ComponentScan.Filter(type = FilterType.ANNOTATION, value = { Controller.class,
                                Component.class }) })
@ImportResource({ "classpath:configuration/spring-config.xml", "classpath:configuration/spring-adapters.xml" })
@EnableMongoRepositories("com.abc.inventory.adjustment.integration.service.audit.repository")
@EnableAutoConfiguration
@EnableMongoAuditing
public class ApplicationConfiguration extends WebMvcConfigurerAdapter {
//

}

添加调试快照

-特杰

【问题讨论】:

  • 这没有意义。请用一些日志确认。指出 Spring Integration 版本。没有taskExecutor,它如何工作?没有@WebAppConfiguration,它如何工作?等等等等。
  • 删除链:
  • 嗨@ArtemBilan 经过一步一步的分析......开始知道,每当消息到达“multiCastChannel”时,订阅者都会被执行两次......我通过删除所有订阅者链和 也和刚刚添加了一个这样的服务激活器: 过程方法调用了两次......我快疯了:( 似乎 pub-sub 频道有问题...
  • 好的。我想请您将其最小化为我可以从我身边测试的东西,并在此处以edit 的形式分享您的问题。谢谢。
  • 如果 pub-sub 频道有问题,我们会知道一段时间。正如我所说:你应该用一些简单的测试用例来证明这一点。

标签: java multithreading junit spring-integration


【解决方案1】:

在这里您可以找到简单的测试用例来演示正确的行为:

<task:executor id="executor" pool-size="2"/>

<publish-subscribe-channel id="pubSubChannel" task-executor="executor" />

<service-activator input-channel="pubSubChannel" expression="T(System).out.println(payload)"/>

<service-activator input-channel="pubSubChannel" expression="T(System).out.println('foo: ' + payload)"/>

@Test
public void testPubSubChannel() throws InterruptedException {
    ConfigurableApplicationContext context = new ClassPathXmlApplicationContext("pubSubChannelConfig.xml", getClass());
    MessageChannel channel = (MessageChannel) context.getBean("pubSubChannel");
    for (int i = 0; i < 10; i++) {
        channel.send(new GenericMessage<Integer>(i));
    }
    Thread.sleep(10000);
    context.close();
}

结果如下:

foo: 0
0
foo: 1
1
2
foo: 2
3
foo: 3
4
foo: 4
5
foo: 5
6
foo: 6
7
foo: 7
8
foo: 8
9
foo: 9

【讨论】:

  • 嗨@ArtemBilan,正如你所建议的,我尝试运行一个与我的要求相同的简单JUNIT...令人惊讶的是它没有问题......但是来到我的应用程序问题仍然存在......可以请你想想是什么让 有这种行为....
  • 添加一点日志harness.jvm.memoryUsage.pools.Compressed-Class-Space.used 被注册为jvm_memoryUsage_pools_Compressed_Class_Space_used 2016-02-19T00:19:50.175Z [harness-metrics-collector STARTING ] INFO c.g.p.h.m.i.HarnessMetricListener - [] - 指标名称harness.logging..debug 正在注册为 logging_debug 2016-02-19T00:19:50.194Z [main] INFO com.abc.service.TestActivator - [] - **** ******************激活********************************** 2016-02- 19T00:19:50.195Z [main] INFO com.abc.service.TestActivator - [] - ********************激活******** ************************
  • 我刚刚使用了一个服务激活器,它有 sysout "******activated*****" 它执行了两次....我刚刚通过调试控制台观察到主线程只为“服务激活器”执行了两次......
  • 请将“org.springframework.integration”类别的调试日志添加到您的问题中,以便分析自己是否无法找出问题。
  • 好的,我正在尝试...我是线程概念的新手...所以尽我所能...感谢您的关注 :)
猜你喜欢
  • 1970-01-01
  • 2011-11-09
  • 1970-01-01
  • 1970-01-01
  • 2022-08-03
  • 2012-10-20
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多