public class ThreadTest {
public static ExecutorService executor = Executors.newFixedThreadPool(10);
public static void main(String[] args) throws ExecutionException, InterruptedException {
// System.out.println("main......start.....");
// Thread thread = new Thread01();
// thread.start();
// System.out.println("main......end.....");
// Runable01 runable01 = new Runable01();
// new Thread(runable01).start();
// FutureTask<Integer> futureTask = new FutureTask<>(new Callable01());
// new Thread(futureTask).start();
// System.out.println(futureTask.get());
// service.execute(new Runable01());
// Future<Integer> submit = service.submit(new Callable01());
// submit.get();
System.out.println("main......start.....");
// CompletableFuture<Void> future = CompletableFuture.runAsync(() -> {
// System.out.println("当前线程:" + Thread.currentThread().getId());
// int i = 10 / 2;
// System.out.println("运行结果:" + i);
// }, executor);
/**
* 方法完成后的处理
*/
// CompletableFuture<Integer> future = CompletableFuture.supplyAsync(() -> {
// System.out.println("当前线程:" + Thread.currentThread().getId());
// int i = 10 / 0;
// System.out.println("运行结果:" + i);
// return i;
// }, executor).whenComplete((res,exception) -> {
// //虽然能得到异常信息,但是没法修改返回数据
// System.out.println("异步任务成功完成了...结果是:" + res + "异常是:" + exception);
// }).exceptionally(throwable -> {
// //可以感知异常,同时返回默认值
// return 10;
// });
/**
* 方法执行完后端处理
*/
// CompletableFuture<Integer> future = CompletableFuture.supplyAsync(() -> {
// System.out.println("当前线程:" + Thread.currentThread().getId());
// int i = 10 / 2;
// System.out.println("运行结果:" + i);
// return i;
// }, executor).handle((result,thr) -> {
// if (result != null) {
// return result * 2;
// }
// if (thr != null) {
// System.out.println("异步任务成功完成了...结果是:" + result + "异常是:" + thr);
// return 0;
// }
// return 0;
// });
/**
* 线程串行化
* 1、thenRunL:不能获取上一步的执行结果
* 2、thenAcceptAsync:能接受上一步结果,但是无返回值
* 3、thenApplyAsync:能接受上一步结果,有返回值
*
*/
CompletableFuture<String> future = CompletableFuture.supplyAsync(() -> {
System.out.println("当前线程:" + Thread.currentThread().getId());
int i = 10 / 2;
System.out.println("运行结果:" + i);
return i;
}, executor).thenApplyAsync(res -> {
System.out.println("任务2启动了..." + res);
return "Hello" + res;
}, executor);
System.out.println("main......end....." + future.get());
}
private static void threadPool() {
ExecutorService threadPool = new ThreadPoolExecutor(
200,
10,
10L,
TimeUnit.SECONDS,
new LinkedBlockingDeque<Runnable>(10000),
Executors.defaultThreadFactory(),
new ThreadPoolExecutor.AbortPolicy()
);
//定时任务的线程池
ExecutorService service = Executors.newScheduledThreadPool(2);
}
public static class Thread01 extends Thread {
@Override
public void run() {
System.out.println("当前线程:" + Thread.currentThread().getId());
int i = 10 / 2;
System.out.println("运行结果:" + i);
}
}
public static class Runable01 implements Runnable {
@Override
public void run() {
System.out.println("当前线程:" + Thread.currentThread().getId());
int i = 10 / 2;
System.out.println("运行结果:" + i);
}
}
public static class Callable01 implements Callable<Integer> {
@Override
public Integer call() throws Exception {
System.out.println("当前线程:" + Thread.currentThread().getId());
int i = 10 / 2;
System.out.println("运行结果:" + i);
return i;
}
}
}
一般来说一个项目里面有一个线程池就够了,需要用到多线程的地方使用该线程池就行;但不排除有些项目会使用到多个线程池,比如项目核心功能使用一个线程池,告警、对接三方等等周边业务使用一个线程池。最好将线程池的参数配置放在配置文件中比如yaml文件,如果采用了nacos等配置中心组件也可以放在其中,如果项目采用了k8s也可以将配置信息放在ConfigMap中。
int corePoolSize:核心线程数即该线程池不会被销毁的线程数量
int maximumPoolSize:最大线程数即该线程池可同时存在的最大线程数量,该参数不会比corePoolSize小
long keepAliveTime:空闲线程存活时长,当线程池中线程数量大于核心线程数之后,并且存在空闲线程的情况下,当空闲时长超过该时长之后则会被销毁,直到剩余线程数量和corePoolSize数量相等
TimeUnit unit:keepAliveTime的单位
BlockingQueue<Runnable> workQueue:等待队列,当线程池创建之后,接受任务的时候如果线程池中线程数量小于核心线程数则会创建线程来执行该任务,如果大于等于核心线程数之后新提交的任务会进入到workQueue中,等待线程池中的空闲线程从workQueue取出执行任务,如果workQueue满了之后,当线程池中线程数小于maximumPoolSize的情况下则会创建线程来执行该任务,如果线程池中的线程数量等于maximumPoolSize则会执行拒绝策略
ThreadFactory threadFactory:创建线程使用的工厂
RejectedExecutionHandler handler:拒绝策略,当线程池满负荷运转之后新进来的任务的处理方式
springboot 整合线程池:
1、创建线程池配置类
@ConfigurationProperties(“thread.pool”):自动读取配置文件中thread.pool开头的配置信息绑定到对应的字段上,绑定规则是将配置文件中的配置去除掉-转为小驼峰就是对应的类中的字段,如thread.pool.core-pool-size对应字段就是corePoolSize。
@Component:将该类交由spring容器管理
@Data:为字段生成get、set方法
@ConfigurationProperties(prefix = "gulimall.thread")
// @Component
@Data
public class ThreadPoolConfigProperties {
private Integer coreSize;
private Integer maxSize;
private Integer keepAliveTime;
}
配置文件中定义配置,当配置文件和配置类都定义了对应属性采用配置文件中的属性值
@EnableConfigurationProperties(ThreadPoolConfigProperties.class)
@Configuration
public class MyThreadConfig {
@Bean
public ThreadPoolExecutor threadPoolExecutor(ThreadPoolConfigProperties pool) {
return new ThreadPoolExecutor(
pool.getCoreSize(),
pool.getMaxSize(),
pool.getKeepAliveTime(),
TimeUnit.SECONDS,
new LinkedBlockingDeque<>(100000),
Executors.defaultThreadFactory(),
new ThreadPoolExecutor.AbortPolicy()
);
}
}
到此,当我们启动spring boot项目的时候会在spring容器中注入一个核心线程数为5、最大线程数10、空闲时间60s、等待队列长度10000、拒绝策略为抛出异常、名称为threadPool的线程池。
在需要用到线程池的类中通过@Resource或@Autowired注入即可使用。
具体用法:
@Override
public SkuItemVo item(Long skuId) throws ExecutionException, InterruptedException {
SkuItemVo skuItemVo = new SkuItemVo();
CompletableFuture<SkuInfoEntity> infoFuture = CompletableFuture.supplyAsync(() -> {
//1、sku基本信息的获取 pms_sku_info
SkuInfoEntity info = this.getById(skuId);
skuItemVo.setInfo(info);
return info;
}, executor);
CompletableFuture<Void> saleAttrFuture = infoFuture.thenAcceptAsync((res) -> {
//3、获取spu的销售属性组合
List<SkuItemSaleAttrVo> saleAttrVos = skuSaleAttrValueService.getSaleAttrBySpuId(res.getSpuId());
skuItemVo.setSaleAttr(saleAttrVos);
}, executor);
CompletableFuture<Void> descFuture = infoFuture.thenAcceptAsync((res) -> {
//4、获取spu的介绍 pms_spu_info_desc
SpuInfoDescEntity spuInfoDescEntity = spuInfoDescService.getById(res.getSpuId());
skuItemVo.setDesc(spuInfoDescEntity);
}, executor);
CompletableFuture<Void> baseAttrFuture = infoFuture.thenAcceptAsync((res) -> {
//5、获取spu的规格参数信息
List<SpuItemAttrGroupVo> attrGroupVos = attrGroupService.getAttrGroupWithAttrsBySpuId(res.getSpuId(), res.getCatalogId());
skuItemVo.setGroupAttrs(attrGroupVos);
}, executor);
// Long spuId = info.getSpuId();
// Long catalogId = info.getCatalogId();
//2、sku的图片信息 pms_sku_images
CompletableFuture<Void> imageFuture = CompletableFuture.runAsync(() -> {
List<SkuImagesEntity> imagesEntities = skuImagesService.getImagesBySkuId(skuId);
skuItemVo.setImages(imagesEntities);
}, executor);
CompletableFuture<Void> seckillFuture = CompletableFuture.runAsync(() -> {
//3、远程调用查询当前sku是否参与秒杀优惠活动
R skuSeckilInfo = seckillFeignService.getSkuSeckilInfo(skuId);
if (skuSeckilInfo.getCode() == 0) {
//查询成功
SeckillSkuVo seckilInfoData = skuSeckilInfo.getData("data", new TypeReference<SeckillSkuVo>() {
});
skuItemVo.setSeckillSkuVo(seckilInfoData);
if (seckilInfoData != null) {
long currentTime = System.currentTimeMillis();
if (currentTime > seckilInfoData.getEndTime()) {
skuItemVo.setSeckillSkuVo(null);
}
}
}
}, executor);
//等到所有任务都完成
CompletableFuture.allOf(saleAttrFuture,descFuture,baseAttrFuture,imageFuture,seckillFuture).get();
return skuItemVo;
}