今天实现了一个小功能,为自己的小项目奠定了一个小基础,现在这个功能已经优化到了200ms左右,文件数组上传,目前还没有外加ftp服务器进行资源管理。为此记录一下自己的学习路线。
首先介绍一下线程池,我理解的线程池其实挺浅的,只能表面的说出其意义,之前大部分都在写单线程(普通io操作)比如一个文件上传获取 ,刚开始没接触线程池的时候是这样写的,直接遍历然后将文件以文件流进行读写,但是现在了解了多线程以及带有缓存的线程池就要用上了,目前效果还是不错的来了解下各种线程池吧;
1. Executors工厂创建线程
- newCachedThreadPool()创建一个具有缓存功能的线程池。
- newFixedThreadPool() 创建一个可重用的、具有固定线程数的线程池
- newSingleThreadExecutor() 相当于newFixedThreadPool(1)
- newScheduledThreadPool() 看这个线程池的名字就有点像定时线程不错他可以在制定延迟后执行线程任务。
- newWorkStealingPool(int) 创建有足够的线程的线程池来支持给定的并行级别,该方法还会使用多个队列来减少竞争(挺有意思的队列都有了)
- newWorkStealingPool()上面那个方法的简化版获取机器的cpu来给定并行的值
2.ExecutorService
这个类其实是Executors的子类,只不过加了几个比较好用的方法列如:
- submit()提交一个线程,其实还有好几种用法,这里就不写了不是很难理解,最简单的就是提交一个参数
- ScheduledFuture 这里又是定时不过这个定时是指定一个任务在多长时间延迟后触发
- shutdown() 这个方法是等待所有线程池里面的线程结束
- shutdownNow() 立马结束所有所有线程池
- awaitTermination() 等待所有线程多长时间,期间会堵塞线程
文件上传示例:
//创建一个5个线程数的线程池
ExecutorService ex = Executors.newFixedThreadPool(5);
List<String> list = new ArrayList<>();
BaseResult<List<String>> result = new BaseResult<>();
if (files.length > 0) {
//循环遍历MultipartFile数组
for (MultipartFile muf :
files) {
//匿名内部类提交线程
ex.submit(() -> {
try {
String end = muf.getOriginalFilename().substring(muf.getOriginalFilename().lastIndexOf(".") + 1);
File file = new File("/Users/Admin/Downloads/download/" + UUID.randomUUID().toString().replaceAll("-", "") + "." + end);
muf.transferTo(file.getAbsoluteFile());
list.add(file.getAbsolutePath());
} catch (Exception e) {
throw new RuntimeException(e.getMessage());
}
});
}
//等待所有线程执行完毕
ex.shutdown();
try {
//如果线程在一定时间内没有完成则立即关闭
if (!ex.awaitTermination(50, TimeUnit.SECONDS)) {
ex.shutdownNow();
}
} catch (InterruptedException e) {
e.printStackTrace();
//异常立即关闭线程池
ex.shutdownNow();
}
result.setCode(200);
result.setData(list);
result.setMsg("上传成功");
第一次上传6个文件所耗时间
第二次上传6个文件所耗时间
本次测试忽略网络,仅在本地测试测得时间
以上就是我今天为我项目所打得一个小基础,明天整合队列进行下一步优化