一、java ExecutorService实现
创建ExecutorService变量
private ExecutorService executor = null
2.执行对应任务时,首先生成线程池
executor = Executors.newFixedThreadPool(线程池大小);
3.循环执行线程
for (String str : ids) {
executor.submit(new Callable() {
@Override
public Void call() throws Exception {
......;//线程执行具体内容
return null;
}
});
}
4.关闭线城池, shutdown关闭线城池,执行后程序会继续往下进行,线城池会等待所有线程线程执行完毕后关闭。
executor.shutdown();
5.设置阻塞等待awaitTermination, awaitTermination的作用是阻塞程序往下进行,使用之后程序会在所有线程执行完毕,关闭线城池之后才可以继续进行。但是如果超过等待时间则会抛出InterruptedException异常
try {
//设置最大阻塞时间,所有线程任务执行完成再继续往下执行
executor.awaitTermination(1, TimeUnit.HOURS);
long endTime = System.currentTimeMillis();
} catch (InterruptedException e) {
}
例
@Service
public class DataImpl extends DataService {
//设置线城池大小
public static final int THREAD_POOL_FIX_SIZE = 100;
@Autowired
private DataDao dataDao;
//线城池服务
private ExecutorService executor = null;
public void createData(Integer totalSize, Integer pageSize) {
//由于每次线程执行完毕会关闭线城池,所以要重新获取线城池
executor = Executors.newFixedThreadPool(THREAD_POOL_FIX_SIZE);
//多线程调用
for(List id :ids){
executor.submit(new Callable() {
@Override
public Void call() throws Exception {
createData(id);
return null;
}
});
}
//关闭线城池
executor.shutdown();
try {
//设置最大阻塞时间,所有线程任务执行完成再继续往下执行
executor.awaitTermination(24, TimeUnit.HOURS);
long endTime = System.currentTimeMillis();
logger.info("=====================结束,用时"+ (endTime-startTime) + "毫秒" );
} catch (InterruptedException e) {
logger.info("======================超时" );
}
}
private void createData(String id){
……
}
}
*注:1.Executors.newFixedThreadPool(THREAD_POOL_FIX_SIZE);要在每次调用方法的时候创建,线程全部执行完成之后shundown(),释放所有线程,这样可以保证执行任务时生成足够线程,线程执行完立即释放。
2. ExecutorService可以写在没个类内,单独问此类使用,不同类之间互不干扰;也可以也成公用方法,写成公用方法后也会变成多类(多任务共享)同Spring线城池类似。
二、Spring 配置线程池(threadPoolTaskExecutor)
corePoolSize: 线程池维护线程的最少数量
keepAliveSeconds 线程池维护线程所允许的空闲时间
maxPoolSize 线程池维护线程的最大数量
queueCapacity 线程池所使用的缓冲队列
rejectedExecutionHandler 线程池拒绝处理策略
当一个任务通过execute(Runnable)方法欲添加到线程池时:
l 如果此时线程池中的数量小于corePoolSize,即使线程池中的线程都处于空闲状态,也要创建新的线程来处理被添加的任务。
l 如果此时线程池中的数量等于 corePoolSize,但是缓冲队列 workQueue未满,那么任务被放入缓冲队列。
l 如果此时线程池中的数量大于corePoolSize,缓冲队列workQueue满,并且线程池中的数量小于maximumPoolSize,建新的线程来处理被添加的任务。
l 如果此时线程池中的数量大于corePoolSize,缓冲队列workQueue满,并且线程池中的数量等于maximumPoolSize,那么通过 handler所指定的策略来处理此任务。也就是:处理任务的优先级为:核心线程corePoolSize、任务队列workQueue、最大线程 maximumPoolSize,如果三者都满了,使用handler处理被拒绝的任务。
l 当线程池中的线程数量大于 corePoolSize时,如果某线程空闲时间超过keepAliveTime,线程将被终止。这样,线程池可以动态的调整池中的线程数。
*注:1.spring 配置的线城池(threadPoolTaskExecutor)由于是spring创建注入的,在首次使用之后,会一直保持corePoolSize个空闲线程,它只会把多余的空闲线程在keepAliveSeconds 时间之后释放,而且线城池不能调用shutdown()方法,否则再次调用,由于线程池已经关闭,会报错。
2. threadPoolTaskExecutor也可以在配置文件配置多个线城池,防止多有任务之间竞争,或者由于不同任务使用的线城池大小不同等情况。
三、ExecutorService与threadPoolTaskExecutor对比
---------------------
作者:黑桃K_程序猿
来源:CSDN
原文:https://blog.csdn.net/kai763253075/article/details/53033853