今天在工作中遇到一个问题,当接口中的列表长度太长,for循环遍历时间就会变得很长,接口的响应速度就会变得很慢,于是我就想,如何使用线程池来优化接口响应时间呢?
一、
1、创建一个固定长度的线程池
ExecutorService pool=Executors.newFixedThreadPool(courseList.size());
2、在for循环创建线程任务并提交给线程池
for (int i=0;i<courseList.size();i++){
Runnable run = new Runnable() {
public void run() {
try {
System.out.println("执行相关代码");
} catch (Exception e) {
e.printStackTrace();
}finally {
countDownLatch.countDown();
}
}
};
pool.submit(run);
}
3、销毁线程池
pool.shutdown();
二、但是在使用的过程中又遇到一个问题,主线程和线程池中的线程是同时执行的,就会导致提前返回,那要如何将线程池中的线程执行完后,再继续执行主线程的代码呢?
1、定义一个CountDownLatch 计数器,初始值设置为列表长度
final CountDownLatch countDownLatch = new CountDownLatch(courseList.size());
2、在线程池的线程执行结束后finally中调用countDown()方法,将CountDownLatch 计数器的值减一。
for (int i=0;i<courseList.size();i++){
Runnable run = new Runnable() {
public void run() {
try {
System.out.println("执行相关代码");
} catch (Exception e) {
e.printStackTrace();
}finally {
countDownLatch.countDown();
}
}
};
pool.submit(run);
}
3、当线程池中的线程都执行完毕,再去执行主线程的代码
try {
// 等待所有线程全部释放完成后,再去执行主线程
countDownLatch.await();
} catch (Exception e) {
e.printStackTrace();
}
三、附赠上我的代码,大家可以参考一下。
final CountDownLatch countDownLatch = new CountDownLatch(courseList.size());
ExecutorService pool=Executors.newFixedThreadPool(courseList.size());
for (int i=0;i<courseList.size();i++){
Integer courseId=(Integer) courseList.get(i).get("id");
String courseName= (String) courseList.get(i).get("name");
Integer index=i;
Runnable run = new Runnable() {
public void run() {
try {
// 记录课程学习详细状态
LinkedHashMap<Object,Object> courseInfoDetail = Maps.newLinkedHashMap();
List<Object> chapterInfoDetailList = Lists.newArrayList();
// 1. 获取用户课程章节学习状态列表
//courseInfoDetail = getUserCourseStudyInfo(userId,userCourse.getCourseId());
courseInfoDetail = getUserCourseStudyInfo(userId,courseId);
System.out.println(courseInfoDetail);
// 2. 获取用户章节详细信息和完成时间-即每个章节的完成情况,完成了多少个章节视频,完成一个章节用时
// List<StuChapter> stuChapterList = stuChapterMapper.selectChapterStatusList(userId,userCourse.getCourseId());
List<StuChapter> stuChapterList = stuChapterMapper.selectChapterStatusList(userId,courseId);
for (int j = 0; j < stuChapterList.size(); j++) {
LinkedHashMap<Object,Object> chapterInfoDetail = Maps.newLinkedHashMap();
//chapterInfoDetail = getChapterStudyInfo(userId,userCourse.getCourseId(),stuChapterList.get(i));
chapterInfoDetail = getChapterStudyInfo(userId,courseId,stuChapterList.get(j));
chapterInfoDetail.put("chapterName",stuChapterList.get(j).getChapterName());
chapterInfoDetailList.add(chapterInfoDetail);
}
// 3. 获取用户课程学习进度指标
// String courseIndex = getCourseAbilityIndex(userId,userCourse.getCourseId());
String courseIndex = getCourseAbilityIndex(userId,courseId);
// 4. 整理用户课程学习详细信息
//courseInfoDetail.put("courseId",userCourse.getCourseId());
courseInfoDetail.put("courseId",courseId);
courseInfoDetail.put("courseIndex",courseIndex);
//courseInfoDetail.put("courseName",userCourse.getCourseName());
courseInfoDetail.put("courseName",courseName);
courseInfoDetail.put("chapterDetail",chapterInfoDetailList);
//studyInfoDetailList.add(index,courseInfoDetail);
studyInfoDetailList[index]=courseInfoDetail;
System.out.println("执行完之前"+studyInfoDetailList);
} catch (Exception e) {
e.printStackTrace();
}finally {
countDownLatch.countDown();
}
}
};
pool.submit(run);
}
try {
// 等待所有线程全部释放完成后,再去执行主线程
countDownLatch.await();
} catch (Exception e) {
e.printStackTrace();
}
List<Object> studyDetailList=Arrays.asList(studyInfoDetailList);
四、最后接口的响应速度也有了很大的提升,嘻嘻嘻 :)