使用Executors创建
import java.util.concurrent.Executors;
import java.util.concurrent.ExecutorService;
ExecutorService executorService = Executors.newCachedThreadPool();
executorService.execute(
//要运行的线程
);
不足
容易资源耗尽
- newFixedThreadPool和newSingleThreadExecutor:
主要问题是堆积的请求处理队列可能会耗费非常大的内存,甚至OOM。
- newCachedThreadPool和newScheduledThreadPool:
主要问题是线程数最大数是Integer.MAX_VALUE,可能会创建数量非常多的线程,甚至OOM。
推荐方案1:手动创建,指定线程池大小
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.ScheduledThreadPoolExecutor;
import org.apache.commons.lang3.concurrent.BasicThreadFactory;
ScheduledExecutorService executorService = new ScheduledThreadPoolExecutor(1,
new BasicThreadFactory.Builder().namingPattern("example-schedule-pool-%d").daemon(true).build());
executorService.execute(()->{
System.out.println("testScheduledExecutorService:"+System.currentTimeMillis());
});
其中
ScheduledExecutorService extends ExecutorService
ScheduledThreadPoolExecutor(int corePoolSize, ThreadFactory threadFactory)
推荐方案2:使用spring创建
//配置
<bean id="cmqExecutor" class="org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor">
<!-- 线程池维护线程的最少数量 -->
<property name="corePoolSize" value="5" />
<!-- 允许的空闲时间 -->
<property name="keepAliveSeconds" value="200" />
<!-- 线程池维护线程的最大数量 -->
<property name="maxPoolSize" value="200" />
<!-- 缓存队列 -->
<property name="queueCapacity" value="1000" />
<!-- 对拒绝task的处理策略 -->
<property name="rejectedExecutionHandler">
<bean class="java.util.concurrent.ThreadPoolExecutor$CallerRunsPolicy" />
</property>
</bean>
//调用
@Autowired
private ThreadPoolTaskExecutor cmqExecutor;
cmqExecutor.execute(
()->{
//TODO
}
);
线程执行优先级
核心线程corePoolSize>任务队列workQueue>最大线程 maximumPoolSize>如果三者都满则使用handler处理被拒绝的任务。
如果此时线程池中的数量小于corePoolSize,即使线程池中的线程都处于空闲状态,也要创建新的线程来处理被添加的任务。
如果此时线程池中的数量等于 corePoolSize,但是缓冲队列 workQueue未满,那么任务被放入缓冲队列。
如果此时线程池中的数量大于等于corePoolSize,缓冲队列workQueue满,并且线程池中的数量小于maxPoolSize,建新的线程来处理被添加的任务。
如果此时线程池中的数量大于corePoolSize,缓冲队列workQueue满,并且线程池中的数量等于maxPoolSize,那么通过handler所指定的策略来处理此任务。
当线程池中的线程数量大于corePoolSize时,如果某线程空闲时间超过keepAliveTime,线程将被终止。这样,线程池可以动态的调整池中的线程数。