一、java ExecutorService实现
- 创建ExecutorService变量
private ExecutorService executor = null
2.执行对应任务时,首先生成线程池
executor = Executors.newFixedThreadPool(线程池大小);
3.循环执行线程
for (String str : ids) {
executor.submit(new Callable<Void>() {
@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<String> id :ids){
executor.submit(new Callable<Void>() {
@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对比
|
threadPoolTaskExecutor |
ExecutorService(Executors.newFixedThreadPool(线程池大小);) |
创建方式 |
配置文件配置比较方便简单 |
可以没有类中单独编写,也可以写成通用类调用 |
核心线程数 |
corePoolSize |
线程池大小 |
最大线程数 |
maxPoolSize |
线程池大小 |
线程所允许的空闲时间 |
keepAliveSeconds |
0 |
缓冲队列大小 |
queueCapacity |
MAX_VALUE = 0x7fffffff |
线程池拒绝处理策略
|
rejectedExecutionHandler |
缓冲队列那么大不会拒绝吧。 |
线程执行完处理 |
保留核心线程数量个线程继续等待连接,不能shutdown,awaitTermination |
可以shutdown,awaitTermination方便处理一些所有线程全部执行完才能够调用的服务接口等。 |
|