线程池的使用
根据项目需要进行对图片的压缩和上传,但由于压缩和上传相应时间比较长,返回时间不在允许范围内故此需要优化;优化方案最终采用线程池的形式降低系统资源消耗,以下为实现过程
逻辑层调用
1.把任务数据封装到CompressAndUpLoadFileTask;
2.调用 consumerUtil.putTask(task);把封装类放入到队列中去
String path= picts.getPicPath();//图片原地址
compresspath = path.substring(0,path.lastIndexOf("."))+"-compress"+path.substring(path.lastIndexOf("."));//压缩后地址
//使用线程池进行文件的上传和压缩
//初始化任务数据
CompressAndUpLoadFileTask task= new CompressAndUpLoadFileTask(path,compresspath, compresspath);
consumerUtil.putTask(task);
任务的数据封装类
@Data
public class CompressAndUpLoadFileTask {
private String srcPath;
private String compressPath;
private String uploadPath;
public CompressAndUpLoadFileTask(String srcPath, String compressPath, String uploadPath) {
this.srcPath = srcPath;
this.uploadPath = uploadPath;
this.compressPath = compressPath;
}
public CompressAndUpLoadFileTask(String srcPath) {
this.srcPath = srcPath;
}
}
接下来查看 consumerUtil类的具体实现
不难发现,consumerUtil先是创建了一个大小为1千的ArrayBlockingQueue的消息队列
@Component
public class ConsumerUtil implements InitializingBean, BeanPostProcessor {
private ArrayBlockingQueue<CompressAndUpLoadFileTask> arrayBlockingQueue = new ArrayBlockingQueue(1000);
private static volatile ConsumerUtil consumerUtil = null;
private Thread consumerThread = null;
private volatile boolean isStop = false;
@Value(value = "${aicar.remote.sshname}")
private String sshname;
@Value(value = "${aicar.remote.sshpasword}")
private String sshpasword;
@Value(value = "${aicar.remote.sshhost}")
private String sshhost;
@Value(value = "${aicar.remote.sshport}")
private Integer sshport;
private final ThreadPoolExecutor executor = (ThreadPoolExecutor) Executors.newFixedThreadPool(8); // 创建一个大小为8的固定线程池,可以按照CPU的核数初步判定,如果CPU密集性任务则创建N+1个,如果是IO密集型任务则创建2N+1个,其中N即CPU的核数
private ConsumerUtil (){
consumerThread = new Thread(){
@SneakyThrows
@Override
public void run() {
while (true){
CompressAndUpLoadFileTask task = arrayBlockingQueue.poll(3, TimeUnit.SECONDS);
if(task==null){
continue;
}
if(isStop){
return;
}
//图片存到服务器对应文件夹下
executor.execute(new Runnable() {
public void run() {
// 打印正在执行的缓存线程信息
ReduceImgUtil.reduceImg(task.getSrcPath(),task.getCompressPath());//压缩图片
try {
new SftpUploadUtil(sshname, sshpasword, sshhost, sshport).uploadFile(task.getUploadPath(),task.getCompressPath());
} catch (SftpException e) {
e.printStackTrace();
}
}
});
}
}
};
consumerThread.start();
}
public void stop(){
isStop = true;
}
public void putTask(CompressAndUpLoadFileTask upLoadFileTask){
try {
this.arrayBlockingQueue.put(upLoadFileTask);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
@Override
public void afterPropertiesSet() throws Exception {
}
@Data
public static class CompressAndUpLoadFileTask {
public CompressAndUpLoadFileTask(String srcPath, String compressPath,String uploadPath) {
this.srcPath = srcPath;
this.uploadPath = uploadPath;
this.compressPath = compressPath;
}
public CompressAndUpLoadFileTask(String srcPath) {
this.srcPath = srcPath;
}
private String srcPath;
private String compressPath;
private String uploadPath;
}
}
其实类在加载的时候线程已经启动了
ConsumerUtil工具类创建了一个大小为8的固定线程池
这一部分就是我们主要的任务,压缩图片然后进行图片上传操作