使用线程池ThreadPool来提高效率,如本项目中模拟多线程下载视频和单线程下载视频所使用的时间消耗长短。
之前写了个抖音视频下载由于每一次,搜索出来的视频都不一样导致下载视频的大小也不一致这样就没办法比较多线程和单线程的效率, 所以这一次在下载方法里面采用睡眠当前线程的方式模拟视频下载。
创建线程池对象:
/**
* @Author itmei
* @Date 2023/3/16
* @description: 线程池对象
* @Title: ThreadPoolConfig
* @Package com.itmei.threadpool.config
*/
@Configuration
public class ThreadPoolConfig {
/**
* 核心池大小
*/
private final int corePoolSize = 50;
/**
* 最大创建线程数
*/
private final int maxPoolSize =100;
/**
* 线程池维护线程允许的空闲时间 (默认60秒)
*/
private final int keepAliveSeconds = 300;
/**
* 队列最大长度
*/
private final int queueCapacity = 1000;
@Bean(name = "threadPoolTaskExecutor")
public ThreadPoolTaskExecutor threadPoolTaskExecutor(){
ThreadPoolTaskExecutor taskExecutor=new ThreadPoolTaskExecutor();
taskExecutor.setCorePoolSize(corePoolSize);
taskExecutor.setMaxPoolSize(maxPoolSize);
taskExecutor.setKeepAliveSeconds(keepAliveSeconds);
taskExecutor.setQueueCapacity(queueCapacity);
// 线程池对拒绝任务(无线程可用)的处理策略
taskExecutor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy());
return taskExecutor;
}
}
模拟下载:
@Service
public class VideoService implements ApplicationRunner {
@Resource
private ThreadPoolTaskExecutor taskExecutor;
private final Logger log = LoggerFactory.getLogger(VideoService.class);
/**
* 是否开启多线程
*/
private boolean threadFlag = true;
@Override
public void run(ApplicationArguments args) throws Exception {
init();
}
public void download(){
try {
//模拟睡眠10秒,比作下载视频所需要的时间
log.info("线程{}开始下载",Thread.currentThread().getName());
Thread.sleep(10*1000);
log.info("线程{}下载完成",Thread.currentThread().getName());
} catch (InterruptedException e) {
e.printStackTrace();
}
}
public void init(){
//模拟下载5个视频
int videos = 5;
long startTime = System.currentTimeMillis();
log.info("》》》开始下载视频《《《");
for (int i = 0; i < videos; i++) {
if (threadFlag){
taskExecutor.execute(() -> {
//线程任务
download();
});
}else {
download();
}
}
//需要等待子线程完成后再走主线程
while (threadFlag){
try {
int activeCount = taskExecutor.getActiveCount();
if (activeCount == 0) {
break;
}
//让主线程等待个1秒减少while的次数
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
long endTime = System.currentTimeMillis();
log.info("总耗时:{} 秒!",(endTime-startTime)/1000);
}
}
运行效果:
多线程运行
单线程运行
可以在下面效果中看出单线程的效率只有一个主线程在跑。