使用线程池优化多任务 ThreadPoolExecutor
看优化最终效果:
System.out.println("耗时:" + (end - start));
// 毫秒 耗时1:28057 耗时2:27347 仅对获取用户信息方法优化后-总耗时:14288
setCorePoolSize:设置核心池大小
setMaximumPoolSize:设置线程池最大能创建的线程数目大小
keepAliveTime是线程池中空闲线程等待工作的超时时间
注意:setMaximumPoolSize之所以设置Integer.MAX_VALUE,是因为for数目太多了,设置小了等待的线程太多会不再给排队等待线程,进行抛弃提示错误。所以这里作为我的测试方法,直接取这个很大值Integer.MAX_VALUE(2147483647),正式使用建议不要这样,使用合理的最大创建线程数目大小。
仅测试练习使用,正式使用需要专研一下线程池的原理
......
public static boolean getData(Long id) throws ApiException, IOException {
ThreadPoolExecutor executor = new ThreadPoolExecutor(5, Integer.MAX_VALUE, 2, TimeUnit.MINUTES,
new ArrayBlockingQueue<Runnable>(5));
getDep(id); // 获取部门
for (Long setId : depSet) { // 将for循环的内容丢进线程池,每个部门id对应一个等待的获取线程
if (!executor.isShutdown()) { // 关闭了吗
GetDetail get = new GetDetail(setId); // new出新的使用构造方法赋值
executor.execute(get); // 执行
System.out.println("线程池中线程数目:"+executor.getPoolSize()+",队列中等待执行的任务数目:"+
executor.getQueue().size()+",已执行玩别的任务数目:"+executor.getCompletedTaskCount());
}
}
executor.shutdown(); // 关闭,但并不是真正的关闭,不再接受新任务并创建等待的线程,已进入线程池的继续执行
System.out.println("【用户userIdSet】长度:" + userIdSet.size());
while (true) {
if (executor.isTerminated()) { // 判断线程池的最后一条线程终止了吗,代表真正的结束
return true;
}
}
}
static class GetDetail implements Runnable {
private long setId;
public getDetail(Long setId){ // 初始的构造方法
this.setId = setId;
}
@SneakyThrows
@Override
public void run() {
JSONObject jsonObject = getUser(setId);
// 钉钉报错调用当前接口次数过多,请求被暂时禁用
// 所以这里判断是否禁用了,再重新获取一次
if (jsonObject.getInteger("errcode") == 88) {
Thread.currentThread().sleep(1000);
jsonObject = getUser(setId);
}
if (jsonObject.getInteger("errcode") == 0) {
JSONObject result = jsonObject.getJSONObject("result");
JSONArray jsonArray = result.getJSONArray("list");
for (Object json : jsonArray) {
JSONObject jo = (JSONObject) json;
String name = jo.getString("name");
......
......
}
}
}
}