首先创建一个java文件:
NewThread.java
@Slf4j
public class NewThread implements Runnable {
public void download(String dir , String file){
//业务内容
}
@Override
public void run() {
// System.out.println("开启了一个新线程");
//可以按顺序运行内容,也可以直接运行内部的内容;直接运行内部内容的时候run()会优先运行
// download(file);
}
}
然后在
controller
当中运行内部程序【因为需要传参】,多个请求可以在new Thread
当中机型for循环
执行方式为按照for循环顺序执行
NewThread newThread = new NewThread();
newThread.download(dir,photoUrl);
Thread thread = new Thread(newThread);
//thread.setName("downloads");
thread.start();
简版:【直接运行run方法,没有任何传参】
NewThread newThread = new NewThread();
Thread thread = new Thread(newThread);
thread.start();
优点:每个内容顺序执行,不会出现极高并发,访问网站和云资源的时候,不容易被识别、封号
缺点:在线程完全运行结束之前,不会给接口返回结果,前台提交请求后长时间不会得到回复
实现类:Impl:
@Slf4j
@Service
@DS("master")
public class GetImgServiceImpl extends ServiceImpl<xxxxxxMapper, 实体类> implements xxxxxxxService {
@Async
@Override
public void getImg(String photoUrl, JSONObject jsonObject) throws IOException, ParseException {
//业务内容
}
}
重点在于在实现类当中使用
@Async
@Override
controller:
for (int i = 0; i <newans.size() ; i++) {
xxxxxxxService .getImg(photoUrl,jsonObject);
}
优点:轻松跑出几百线程;
缺点,对于对方服务器压力巨大。
执行效果:线程编号瞬间达到120+,然后纷纷结束。(并不是按照发起的顺序结束的)
新建配置类,重点在于@Bean
的名字,如果只有一个线程池则可以不写
@Configuration
@EnableAsync
public class AsyncConfigurer {
@Bean("normalThreadPool") //线程池实例名,多个线程池配置需要声明,一个线程池可有可无
public ThreadPoolTaskExecutor executor(){
ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
//配置核心线程数
executor.setCorePoolSize(15);
//配置最大线程数
executor.setMaxPoolSize(30);
//配置队列大小
executor.setQueueCapacity(10000);
//线程的名称前缀
executor.setThreadNamePrefix("normalThreadPool-");
//线程活跃时间(秒)
//executor.setKeepAliveSeconds(60);
//等待所有任务结束后再关闭线程池
executor.setWaitForTasksToCompleteOnShutdown(true);
//设置拒绝策略
//executor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy());
//执行初始化
executor.initialize();
return executor;
}
}
controller:正常不变即可
for (int i = 0; i <newans.size() ; i++) {
xxxxxxxService .getImg(photoUrl,jsonObject);
}
Impl:重点在于@Async("normalThreadPool")
里面的名字
@Async("normalThreadPool") //多个线程池配置时需指定配置实例
@Override
public void getImgLimit(String photoUrl, JSONObject jsonObject) throws IOException, ParseException {
//业务内容
}
执行效果:控制在15个线程左右。
由于返回后get方法会有阻塞,所以一般使用数据库或者redis进行存储,来达到能够浏览进度的效果
Impl:
@Async("normalThreadPool")
public CompletableFuture<String> task() {
String result = "";
return CompletableFuture.completedFuture(result);
controller:
CompletableFuture<String> result = taskService.task();
log.info("result:{}", result.get()); // get 方法会使主线程阻塞