Spring ThreadPoolTask​​Executor waitForTasksToCompleteOnShutdown行为不明确

时间:2016-07-14 15:50:10

标签: java spring multithreading spring-boot

在我的Spring boot应用程序Web容器中禁用。因此,当我开始应用程序时,它可以正常运行并关闭自己。我在服务中使用@Async方法并从jUnit测试运行它。它在并行线程中应该工作。但应用程序关闭的问题。当jUnit测试完成Spring Boot关闭应用程序但@Async线程仍然并行运行时,我得到了一个异常。要使@Async线程能够在关闭之前完成,我将 waitForTasksToCompleteOnShutdown 属性设置为 true 。之后 Spring Boot关闭但并行线程没有完成,甚至没有异常捕获。为什么?在并行线程完成之前如何强制Spring Boot不关闭?

此处app输出waitForTasksToCompleteOnShutdown = false

Test thread closed
Thread sleep intrerrupted - async method test url string 2
Thread sleep intrerrupted - async method test url string 4
Thread sleep intrerrupted - async method test url string 0
Thread sleep intrerrupted - async method test url string 3
Thread sleep intrerrupted - async method test url string 1

此处app输出waitForTasksToCompleteOnShutdown = true。如您所见,@Async方法没有输出任何内容,因此@Async线程未完成其工作:

Test thread closed

更新 作为提出的解决方案,我试图在测试中注入ThreadPoolTask​​Executor bean,但结果不会改变。与以前相同的输出。这里是JUnit测试类:

@RunWith(SpringJUnit4ClassRunner.class)
@SpringApplicationConfiguration(classes = CLApplication.class)
@TestPropertySource(locations="classpath:test.properties")
public class CatalogPageServiceImplTest {

    @Autowired
    CatalogPageService catalogPageService;

    @Resource(name="locationPageExecutor")
    ThreadPoolTaskExecutor locationPageExecutor;

    @Test
    public void processPageTest(){
        for (int i=0; i<5; i++){
            catalogPageService.processPage(
                    new CatalogPage("test url string "+Integer.toString(i)));
        }

        try {
            Thread.sleep(200);
        } catch (InterruptedException e) {
            System.out.println("Test thread sleep intrerrupted");
        }

        locationPageExecutor.shutdown();

        System.out.println("Test thread closed");
    }
}

SpringBoot主类:

@SpringBootApplication
@EnableAsync
public class CLApplication {

    private static final Logger log = LoggerFactory.getLogger(CLApplication.class);

    @Bean
    public TaskExecutor locationPageExecutor() {
        ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
        executor.setCorePoolSize(20);
        executor.setMaxPoolSize(20);
        executor.setQueueCapacity(20);
        executor.setWaitForTasksToCompleteOnShutdown(true);
        return executor;
    }   

    public static void main(String[] args) {
        log.info("Application main method call");
        try{
            SpringApplication.run(CLApplication.class, args);
        }catch(Throwable t){
            log.error("Unexpected error: ",t);
        }
        log.info("Application main method exit");
    }
}

服务:

@Service
public class CatalogPageServiceImpl implements CatalogPageService {

    @Override
    @Async("locationPageExecutor")
    public void processPage(CatalogPage catalogPage) {
        try {
            Thread.sleep(500);
            System.out.println("print from Async method "+catalogPage.getUrl());
        } catch (InterruptedException e) {
            System.out.println("Thread sleep intrerrupted - async method "+catalogPage.getUrl());
        }
    }
}

测试

@RunWith(SpringJUnit4ClassRunner.class)
@SpringApplicationConfiguration(classes = CLApplication.class)
@TestPropertySource(locations="classpath:test.properties")
public class CatalogPageServiceImplTest {

    @Autowired
    CatalogPageService catalogPageService;

    @Test
    public void processPageTest(){
        for (int i=0; i<5; i++){
            catalogPageService.processPage(
                    new CatalogPage("test url string "+Integer.toString(i)));
        }

        try {
            Thread.sleep(200);
        } catch (InterruptedException e) {
            System.out.println("Test thread sleep intrerrupted");
        }
        System.out.println("Test thread closed");
    }
}

0 个答案:

没有答案