在executor中指定线程池大小不起作用

时间:2017-12-01 16:33:10

标签: java spring multithreading threadpool threadpoolexecutor

我有一个春季启动项目。我试图异步调用一些方法。我遵循了这个文档:https://spring.io/guides/gs/async-method/。在Application.java中,我添加了以下方法:

    @Bean
    public Executor asyncExecutor() {
        ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
        executor.setCorePoolSize(2);
        executor.setMaxPoolSize(2);
        executor.setQueueCapacity(500);
        executor.setThreadNamePrefix("Rules-");
        executor.initialize();
        return executor;
    }

请注意我已将池大小设置为2.但是当我调用异步方法5次时,会使用不同的ThreadNamePrefix创建五个不同的线程。

2017-12-01 19:16:00.901  INFO 32000 --- [cTaskExecutor-5] hello world
2017-12-01 19:16:00.930  INFO 32000 --- [cTaskExecutor-4] hello world
2017-12-01 19:16:01.372  INFO 32000 --- [cTaskExecutor-1] hello world
2017-12-01 19:16:01.376  INFO 32000 --- [cTaskExecutor-2] hello world
2017-12-01 19:16:01.985  INFO 32000 --- [cTaskExecutor-3] hello world

我不确定它的配置位置。有人可以帮忙吗?

更新

以下是我提交任务的代码:

@Component
public class MyClass {
    @Autowired
    private Async2 async;

    public void someMethod()
    {
        try {
            async.anotherMethod(1);
            async.anotherMethod(2);
            async.anotherMethod(3);
            async.anotherMethod(4);
            async.anotherMethod(5);
        } catch(Exception e) {
            e.printStackTrace();
        }
    }
}

@Service
public class Async2 {
    private static final Logger LOGGER = Logger.getLogger(Async2.class);
    @Async
    public CompletableFuture<Void> anotherMethod(int i) {
        LOGGER.info("hello world");
        return CompletableFuture.completedFuture(null);
    }
}

UPDATE2

@Controller
@RequestMapping("/a")
public class WebController {
    @Autowired
    private MyClass c;

    @RequestMapping(value="/b", method =RequestMethod.POST)
    @ResponseBody Response getResponseForRequest(@RequestBody Request request)
    {
        c.someMethod();
        return new Response();
    }
}

2 个答案:

答案 0 :(得分:1)

似乎未加载具有自定义asyncExecutor的配置类。检查它是否被Spring扫描并且存在@EnableAsync注释。同样在您的示例中,anotherMethod不会返回CompletableFuture

这是最小的工作样本:

@SpringBootApplication
@EnableAsync
@RestController
public class AsyncApp {

    @Bean
    public Executor asyncExecutor() {
        ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
        executor.setCorePoolSize(2);
        executor.setMaxPoolSize(2);
        executor.setQueueCapacity(500);
        executor.setThreadNamePrefix("Rules-");
        executor.initialize();
        return executor;
    }

    @Service
    public class AsyncService {
        @Async
        public CompletableFuture<Void> async() {
            try {
                Thread.sleep(1000L);
            } catch (InterruptedException e) {

            }
            System.out.println("Hello from " + Thread.currentThread().getName());
            return CompletableFuture.completedFuture(null);
        }
    }

    @Autowired
    private AsyncService asyncService;

    @RequestMapping("/test")
    public void test() {
        for (int i = 0; i < 5; i++) {
            asyncService.async();
        }
        System.out.println("Return from Controller");
    }

    public static void main(String[] args) {
        SpringApplication.run(AsyncApp.class, args);
    }
}

输出结果为:

Return from Controller
Hello from Rules-2
Hello from Rules-1
Hello from Rules-2
Hello from Rules-1
Hello from Rules-2

答案 1 :(得分:1)

最后,我得到了解决方案。首先,我必须指定bean的名称并在Async2类中使用bean名称。

@Bean(name="rulesThreadExecutor")
public Executor asyncExecutor() {
    ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
    executor.setCorePoolSize(2);
    executor.setMaxPoolSize(2);
    executor.setQueueCapacity(500);
    executor.setThreadNamePrefix("Rules-");
    executor.initialize();
    return executor;
}

@Async("rulesThreadExecutor")
public CompletableFuture<Void> anotherMethod(int i) {
    LOGGER.info("hello world");
    return CompletableFuture.completedFuture(null);
}