线程池使用实例
先写一个配置类
/**
* 线程池配置
*/
@Configuration
public class ThreadPoolConfig {
//定义线程前缀
public static final String NAME_PRE="test";
/**
* ExecutorService 这个对象就是线程池,可以点进去他的源码看看
* @Bean,将getExecutor()方法返回的对象交给Spring管理
*/
@Bean
public static ExecutorService getExecutor(){
/**
*方法一
*ExecutorBuilder e=new ExecutorBuilder();
*e.setAllowCoreThreadTimeOut(false);
**/
/**方法二直接Builder赋值**/
return ExecutorBuilder.create()
.setCorePoolSize(8)
.setMaxPoolSize(16)
.setKeepAliveTime(60, TimeUnit.SECONDS)
.setHandler(new ThreadPoolExecutor.CallerRunsPolicy())
.setWorkQueue(new LinkedBlockingDeque<>(2000))
.setThreadFactory(ThreadFactoryBuilder.create().setNamePrefix(NAME_PRE).build())
.setAllowCoreThreadTimeOut(false)
.build();
}
}
- ExecutorService 这个对象是线程池
- @Bean,在项目启动时执行ExecutorService类的方法,返回一个对象交给spring管理。
- @Configuration,配置注解,在项目启动时,首先执行这个类的代码。
- 返回的对象第一种方法用set方法去赋值;第二种用Builder赋值。
参数内容为数字也通常为魔法值
方法1、可以放到配置文件中(yml配置)
threadpool:
corepoolsize: 8
maxPoolSize: 16
# 队列大小
dequesize: 2000
# 线程前缀
namepre: test-
方法2、设置静态常量
//定义线程前缀
public static final String NAME_PRE="test";
.setThreadFactory(ThreadFactoryBuilder.create().setNamePrefix(NAME_PRE).build())
这样一个线程池就建好了写好了怎么用呢?
@Resource
private ExecutorService executorService;
写一个测试尝试一下:
Service中写接口
/**Service中写接口**/
void test() throws InterruptedException;
Impl中重写方法(先模拟不用线程池)
@SentinelResource 注解 value指定资源的名称,blockHandler用于指定服务限流后的后续处理逻辑。<!-- 如果要使用@SentinelResource必须添加此依赖 -->
<dependency>
<groupId>com.alibaba.csp</groupId>
<artifactId>sentinel-annotation-aspectj</artifactId>
<version>1.8.1</version>
</dependency>
/**Impl中重写方法**/
@SentinelResource(value = "test",blockHandler="exceptionHandler")
@Override
public Boolean test() throws InterruptedException {
/**模拟业务场景耗时**/
Thread.sleep(100000);
return true;
}
controller中调用接口
/**controller中调用接口**/
@GetMapping("/open/test")
public Boolean test() throws InterruptedException {
userService.test();
return Boolean.TRUE;
}

怎么用线程池?两个方法
方法一 注解方式(用的不多)
方法二 使用CompletableFuture
@Override
public void test() throws InterruptedException {
log.info("进来了");
CompletableFuture.runAsync(()->{
try {
log.info("进来了1111");
/**模拟业务场景耗时**/
Thread.sleep(100000);
} catch (InterruptedException e) {
e.printStackTrace();
}
},executorService);
}




使用多线程的三种形式

===> 适用于更新操作,不关注返回值
===> 适用于多IO操作,如:for循环查数据库、循环调用http接口查询、多次查询数据库操作模拟一下多线程查询
@Override
public void test() throws InterruptedException {
log.info("进来了");
//QueryBo为构建的返回值
QueryBO queryBO=new QueryBO();
//获取开始时间
long start = System.currentTimeMillis();
//创建线程,将任务放到线程池
CompletableFuture<Void> query1 = CompletableFuture.runAsync(() -> {
Boolean aBoolean = null;
try {
aBoolean = query1();
} catch (InterruptedException e) {
e.printStackTrace();
}
queryBO.setQuery1(aBoolean);
}, executorService);
//创建线程,将任务放到线程池
CompletableFuture<Void> query2 =CompletableFuture.runAsync(()-> {
Boolean aBoolean = null;
try {
aBoolean = query2();
} catch (InterruptedException e) {
e.printStackTrace();
}
queryBO.setQuery2(aBoolean);
},executorService);
//创建线程,将任务放到线程池
CompletableFuture<Void> query3=CompletableFuture.runAsync(()-> {
Boolean aBoolean = null;
try {
aBoolean = query3();
} catch (InterruptedException e) {
e.printStackTrace();
}
queryBO.setQuery3(aBoolean);
},executorService);
//将这3个任务放到数组中
CompletableFuture[] completableFutures=Stream.of(query1,query2,query3).collect(Collectors.toList()).toArray(new CompletableFuture[3]);
//当数组里的任务都执行完,聚合一下,这行代码相当于将主线程阻塞住
CompletableFuture.allOf(completableFutures).join();
//打印时间戳
long time = System.currentTimeMillis()-start;
//allOf之后才会执行这句log,验证一下queryBO
log.info("查询结果{},时间差{}",queryBO,time);
}
/**
* 第一个查询,耗时3秒
* @return
* @throws InterruptedException
*/
public Boolean query1()throws InterruptedException{
log.info("进来了1");
Thread.sleep(3000);
return true;
}
/**
* 第二个查询,耗时1秒
* @return
* @throws InterruptedException
*/
public Boolean query2()throws InterruptedException{
log.info("进来了2");
Thread.sleep(1000);
return true;
}
/**
* 第三个查询,耗时5s
* @return
* @throws InterruptedException
*/
public Boolean query3()throws InterruptedException{
log.info("进来了3");
Thread.sleep(5000);
return false;
}
@Data
public class QueryBO {
private Boolean query1;
private Boolean query2;
private Boolean query3;
}

//将这3个任务放到数组中
CompletableFuture[] completableFutures=Stream.of(query1,query2,query3).collect(Collectors.toList()).toArray(new CompletableFuture[3]);
//当数组里的任务都执行完,聚合一下,这行代码相当于将主线程阻塞住
CompletableFuture.allOf(completableFutures).join();
线程不安全问题
