Permalink
Browse files

Create 00443.md

  • Loading branch information...
making committed Jan 10, 2018
1 parent 49bce98 commit 746beaa65a3f2a88ee8c1fb8ee57152590ee8cd2
Showing with 120 additions and 0 deletions.
  1. +120 −0 content/00443.md
View
@@ -0,0 +1,120 @@
---
title: 誤解しがちなThreadPoolTaskExecutorの設定
tags: ["Java", "Spring"]
categories: ["Programming", "Java", "org", "springframework", "scheduling", "concurrent", "ThreadPoolTaskExecutor"]
---
Springの[`TaskScheduler`](https://docs.spring.io/autorepo/docs/spring-framework/5.0.x/spring-framework-reference/integration.html#scheduling)のうち、もっともよく使われる`org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor`の設定ミスが多いです。
* `corePoolSize`
* `maxPoolSize`
* `queueCapacity`
が設定項目としてあります。
これだけ見ると、この`Executor``Thead`を作る順としては
1. `corePoolSize``Thread`を最初に作る
2. `corePoolSize`が一杯になると`maxPoolSize`まで`Thread`を増やす
3. `maxPoolSize`を越えると、`queueCapacity`までキューイングする
4. `queueCapacity`を越えるとrejectされる
と思いがちです。
しかし、これは誤解です。
正しくは
1. `corePoolSize`まで`Thread`を作る
2. `corePoolSize`が一杯になると`queueCapacity`までキューイングする
3. `queueCapacity`を越えると`maxPoolSize`まで`Thread`を増やす
4. `maxPoolSize`を越えるとrejectされる
です。
`corePoolSize`のデフォルト値は`1``maxPoolSize`,`queueCapacity`共にデフォルト値は`Integer.MAX_VALUE`です。
次のような設定は意味がありません。
``` java
@Bean
ThreadPoolTaskExecutor threadPoolTaskExecutor() {
ThreadPoolTaskExecutor taskExecutor = new ThreadPoolTaskExecutor();
taskExecutor.setCorePoolSize(4);
taskExecutor.setMaxPoolSize(40);
return taskExecutor;
}
```
`queueCapacity`を設定していないので、最大スレッド数は`4`です。それ以上のリクエストは全てキューイングされます。`40`という数字に意味がありません。
``` java
@Bean
ThreadPoolTaskExecutor threadPoolTaskExecutor() {
ThreadPoolTaskExecutor taskExecutor = new ThreadPoolTaskExecutor();
taskExecutor.setMaxPoolSize(40);
return taskExecutor;
}
```
`corePoolSize``queueCapacity`を設定していないので、最大スレッド数は`1`です。それ以上のリクエストは全てキューイングされます。
スレッド数を`4`-`40`に設定したいのであれば、例えば次のように設定する必要があります。
``` java
@Bean
ThreadPoolTaskExecutor threadPoolTaskExecutor() {
ThreadPoolTaskExecutor taskExecutor = new ThreadPoolTaskExecutor();
taskExecutor.setCorePoolSize(4);
taskExecutor.setQueueCapacity(25);
taskExecutor.setMaxPoolSize(40);
return taskExecutor;
}
```
あるいはスレッド数`40`に固定したい場合は
``` java
@Bean
ThreadPoolTaskExecutor threadPoolTaskExecutor() {
ThreadPoolTaskExecutor taskExecutor = new ThreadPoolTaskExecutor();
taskExecutor.setCorePoolSize(40);
return taskExecutor;
}
```
でOKです。
設定値を次の順番で認識しておいたほうが間違いにくいです。
* `corePoolSize`
* `queueCapacity`
* `maxPoolSize`
ちなみに`ThreadPoolTaskExecutor`が委譲している`java.util.concurrent.ThreadPoolExecutor`を作るときは次のような使い方をすることが多いと思います。
``` java
ExecutorService executorService = Executors.newFixedThreadPool(40);
```
これは
``` java
@Bean
ThreadPoolTaskExecutor threadPoolTaskExecutor() {
ThreadPoolTaskExecutor taskExecutor = new ThreadPoolTaskExecutor();
taskExecutor.setCorePoolSize(40);
taskExecutor.setMaxPoolSize(40);
return taskExecutor;
}
```
に近いです。

0 comments on commit 746beaa

Please sign in to comment.