线程池与异步任务

线程池与异步任务

复习线程池

在项目中只使用线程池的方式,这种池化技术节省资源开销,能够控制资源

池化技术:事先准备好一些资源,要使用就去池子里拿,用完了要还到池子里去(重复利用)

  1. 实现复用,降低频繁创建,销毁资源的消耗
  2. 提高响应速度,提交任务时不用等待创建线程就能立即执行
  3. 方便管理,控制并发数

复习链接Java中的线程池

CompletableFuture 异步编排

启动异步任务

在这里插入图片描述

Runnable和Supplier都是函数式接口,所以可以使用lambda表达式
在这里插入图片描述

	private static Executor executor = new ThreadPoolExecutor(5, 10,
            60L, TimeUnit.SECONDS,
            new LinkedBlockingQueue<>(), Executors.defaultThreadFactory(),
            new ThreadPoolExecutor.AbortPolicy());

	/**
     * 测试启动异步任务
     */
    private static void test1(){
        //runAsync 无返回值异步任务
        CompletableFuture.runAsync(() -> {
            System.out.println("main start");

            Integer sum = 0;
            for (int i = 0; i < 100; i++) {
                sum += i;
            }
            System.out.println(sum);
            System.out.println("main end");
        }, executor);

        //supplyAsync 有返回值异步任务
        CompletableFuture<Integer> supplyAsync = CompletableFuture.supplyAsync(() -> {
            System.out.println("main start");

            Integer sum = 0;
            for (int i = 0; i < 100; i++) {
                sum += i;
            }
            System.out.println(sum);
            System.out.println("main end");
            return sum;
        }, executor);
        Integer integer = null;
        try {
            integer = supplyAsync.get();
        } catch (InterruptedException e) {
            e.printStackTrace();
        } catch (ExecutionException e) {
            e.printStackTrace();
        }
        System.out.println("sum:"+integer);
    }
完成回调和异常感知
  • 回调感知whenComplete/whenCompleteAsync (带有Async则是继续异步执行)

    • 第一个参数是结果,第二个参数是异常信息
  • 异常感知exceptionally

    • 参数是异常信息
    • 发生异常才会执行
    • 发生异常时相比与whenComplete,exceptionally可以返回默认值
        //supplyAsync 有返回值异步任务
        CompletableFuture<Integer> supplyAsync = CompletableFuture.supplyAsync(() -> {
            System.out.println("main start");

            Integer sum = 100/10;
            System.out.println("main end");
            return sum;
        }, executor).whenComplete((result,exception)->{
            System.out.println("结果:"+result+";异常:"+exception);
        }).exceptionally(exception->{
            //有异常返回默认值
            return 100;
        });
        Integer integer = null;
        try {
            integer = supplyAsync.get();
        } catch (InterruptedException e) {
            e.printStackTrace();
        } catch (ExecutionException e) {
            e.printStackTrace();
        }
        System.out.println("sum:"+integer);

未发生异常结果

在这里插入图片描述

发生异常结果

在这里插入图片描述

异步任务完成时的处理

在异步任务完成后使用handler进行处理

可以把handler看作回调感知和异常感知的结合

 CompletableFuture<Integer> supplyAsync = CompletableFuture.supplyAsync(() -> {
            System.out.println("main start");
            Integer sum = 100 / 0;
            return sum;
        }, executor)
//                .whenComplete((result,exception)->{
//            System.out.println("结果:"+result+";异常:"+exception);
//        }).exceptionally(exception->{
//            System.out.println("exception:"+exception);
//            //有异常返回默认值
//            return 100;
//        });
                .handle((result, exception) -> {
                    if (result != null) {
                        System.out.println("结果:" + result);
                        return result;
                    }

                    if (exception != null) {
                        System.out.println("异常:" + exception);
                        return 100;
                    }

                    return 0;
                });
        Integer integer = null;
        try {
            integer = supplyAsync.get();
        } catch (InterruptedException e) {
            e.printStackTrace();
        } catch (ExecutionException e) {
            e.printStackTrace();
        }
        System.out.println("sum:" + integer);
        System.out.println("main end");

在这里插入图片描述

两任务组合
两组任务完成后要执行的任务

设置两组任务完成后要执行的任务

runAfterBoth(Async):无参数无返回值

在这里插入图片描述

thenAcceptBoth(Async):参数是任务结果,无返回值

在这里插入图片描述

thenCombine(Async)参数是任务结果,有返回值

在这里插入图片描述

两组任务任一任务完成后要执行的任务

这个和上面类似,只是满足条件从两组任务都完成变成了任一任务完成

runAfterEitherAsync无参数无返回值
在这里插入图片描述

acceptEitherAsync参数是完成任务的结果,无返回值
在这里插入图片描述

applyToEitherAsync参数为完成任务的结果,有返回值

在这里插入图片描述

多任务组合

allof 等待多任务完成

在这里插入图片描述

anyof等待任一任务完成

在这里插入图片描述

项目整合异步任务

1.编写线程池配置文件类
@ConfigurationProperties(prefix = "mall.thread")
@Component
@Data
public class ThreadPoolConfigProperties {
    private Integer maxSize;
    private Integer coreSize;
    private Integer keepAliveTime;
}

application.properties中设置值

mall.thread.maxSize=20
mall.thread.coreSize=5
mall.thread.keepAliveTime=20
2.导入依赖
<!--    填写配置文件自动提示的依赖  -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-configuration-processor</artifactId>
            <optional>true</optional>
        </dependency>
3.编写线程池组件
@Configuration
public class ThreadPoolConfig {
    @Bean
    public ThreadPoolExecutor threadPoolExecutor(ThreadPoolConfigProperties pool) {
        return new ThreadPoolExecutor(pool.getCoreSize(), pool.getMaxSize()
                , pool.getKeepAliveTime(), TimeUnit.SECONDS, new LinkedBlockingQueue<>(5000),
                Executors.defaultThreadFactory(), new ThreadPoolExecutor.AbortPolicy());
    }
}
4.编写异步任务核心代码
@Autowired
ThreadPoolExecutor executor;


@Override
    public SkuItemResultVo item(Long skuId) throws ExecutionException, InterruptedException {
        SkuItemResultVo result = new SkuItemResultVo();

        //    1.sku基本信息
        CompletableFuture<SkuInfoEntity> infoFuture = CompletableFuture.supplyAsync(() -> {
            SkuInfoEntity skuInfoEntity = baseMapper.selectById(skuId);
            result.setInfo(skuInfoEntity);
            return skuInfoEntity;
        }, executor);


        //    3.spu销售组合 (1完成后异步执行)
        CompletableFuture<Void> saleFuture = infoFuture.thenAcceptAsync(res -> {
            List<SkuItemSaleAttrVo> saleAttrVos = skuInfoService.getSaleAttrBySpuId(res.getSpuId());
            result.setSaleAttr(saleAttrVos);
        }, executor);


        //    4.spu介绍 (1完成后异步执行)
        CompletableFuture<Void> descFuture = infoFuture.thenAcceptAsync(res -> {
            SpuInfoDescEntity desc = spuInfoDescService.getById(res.getSpuId());
            result.setDesc(desc);
        }, executor);


        //    5.spu规格参数 (1完成后异步执行)
        CompletableFuture<Void> attrFuture = infoFuture.thenAcceptAsync(res -> {
            List<SpuItemAttrGroupVo> attrGroupVos = attrGroupService.getAttrGroupsWithAttrsBySpuId(res.getSpuId(), res.getCatalogId());
            result.setGroupVos(attrGroupVos);
        }, executor);


        //    2.sku图片信息
        CompletableFuture<Void> imagesFuture = CompletableFuture.runAsync(() -> {
            List<SkuImagesEntity> images = skuImagesService.getListBySkuId(skuId);
            result.setImages(images);
        }, executor);

        //等待所有任务执行完毕
        CompletableFuture.allOf(imagesFuture, attrFuture, descFuture, saleFuture).get();
        
        return result;
    }
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Java线程池可以很好地管理和调度多线程任务,实现异步任务。以下是一个简单的示例,演示如何使用Java线程池实现异步任务: ```java import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; public class AsyncTasks { private ExecutorService executorService = Executors.newFixedThreadPool(10); public void runAsyncTask(Runnable task) { executorService.execute(task); } } ``` 在上面的代码中,我们创建了一个名为`AsyncTasks`的类,该类具有一个`ExecutorService`对象,用于管理我们的线程池。我们还定义了一个`runAsyncTask`方法,该方法接受一个`Runnable`对象作为参数,并将其提交给线程池进行异步执行。 要使用这个类,我们可以创建一个新的异步任务并将其传递给`runAsyncTask`方法。例如: ```java public class Main { public static void main(String[] args) { AsyncTasks asyncTasks = new AsyncTasks(); // 创建一个新的异步任务 Runnable task = new Runnable() { @Override public void run() { // 执行异步任务 System.out.println("Async task is running."); } }; // 提交异步任务线程池 asyncTasks.runAsyncTask(task); } } ``` 在这个例子中,我们首先创建了一个`AsyncTasks`对象,然后创建了一个新的`Runnable`对象,该对象包含了我们想要在异步任务中执行的代码。最后,我们将这个`Runnable`对象传递给`runAsyncTask`方法,该方法将任务提交给线程池进行异步执行。 使用Java线程池实现异步任务可以提高程序的并发性和响应性,并且可以有效地管理和调度多线程任务
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值