线程池与CompletableFuture 异步编排

使用线程池的好处:
1、降低资源的消耗
通过重复利用已经创建好的线程降低线程的创建和销毁带来的损耗
2、提高响应速度
因为线程池中的线程数没有超过线程池的最大上限时,有的线程处于等待分配任务
的状态,当任务来时无需创建新的线程就能执行
3、提高线程的可管理性
线程池会根据当前系统特点对池内的线程进行优化处理,减少创建和销毁线程带来
的系统开销。无限的创建和销毁线程不仅消耗系统资源,还降低系统的稳定性,使
用线程池进行统一分配

以下代码首先创建线程池executor ,将其传入异步编排对象CompletableFuture,它提供了四个静态方法来创建一个异步操作。

1、创建异步对象方法

在这里插入图片描述

1、runXxxx 都是没有返回结果的,supplyXxx 都是可以获取返回结果的
2、可以传入自定义的线程池,否则就用默认的线程池
public class Thread1Test {

    public static ExecutorService executor = Executors.newFixedThreadPool(10);

    public static void main(String[] args) throws ExecutionException, InterruptedException {
        System.out.println("方法开始。。。");

        CompletableFuture<Void> future = CompletableFuture.runAsync(() -> {
            System.out.println("当前线程" + Thread.currentThread().getId());
            int i = 10 / 2;
            System.out.println(i);
        }, executor);
        System.out.println("方法结束");

    }
}

在这里插入图片描述

2、计算完成时回调方法

使用supplyAsync可以获得线程运行返回结果:

CompletableFuture<Integer> future = CompletableFuture.supplyAsync(() -> {
            System.out.println("当前线程" + Thread.currentThread().getId());
            int i = 10 / 2;
            System.out.println("运行结果"+i);
            return i;
        }, executor);
        Integer integer = future.get();

提供了计算完成时回调方法,在处理完成后,对结果进行操作:
在这里插入图片描述
whenComplete 可以处理正常和异常的计算结果,exceptionally 处理异常情况。
whenComplete 和 whenCompleteAsync 的区别:
whenComplete:是执行当前任务的线程执行继续执行 whenComplete 的任务。
whenCompleteAsync:是执行把 whenCompleteAsync 这个任务继续提交给线程池
来进行执行。
方法不以 Async 结尾,意味着 Action 使用相同的线程执行,而 Async 可能会使用其他线程
执行(如果是使用相同的线程池,也可能会被同一个线程选中执行)
whenComplete可以得到任务完成结果,参数1是结果,参数2是异常:

CompletableFuture<Integer> future = CompletableFuture.supplyAsync(() -> {
            System.out.println("当前线程" + Thread.currentThread().getId());
            int i = 10 / 0;
            System.out.println("运行结果"+i);
            return i;
        }, executor).whenComplete((res,excption)->{
            System.out.println("异步完成,结果是"+res+"异常是:"+excption);
        });

这里制造除数为0的异常:
在这里插入图片描述
exceptionally虽然能得到异常信息,但是没法修改返回数据,感知异常,返回默认值

 CompletableFuture<Integer> future = CompletableFuture.supplyAsync(() -> {
            System.out.println("当前线程" + Thread.currentThread().getId());
            int i = 10 / 0;
            System.out.println("运行结果"+i);
            return i;
        }, executor).whenComplete((res,excption)->{
            System.out.println("异步完成,结果是"+res+"异常是:"+excption);
        }).exceptionally(throwable -> {
            //感知异常,返回默认值
            return 10;
        });
        Integer integer = future.get();

在这里插入图片描述

3、handle方法

在这里插入图片描述
handle和 complete 一样,可对结果做最后的处理(可处理异常),可改变返回值。

CompletableFuture<Integer> future = CompletableFuture.supplyAsync(() -> {
            System.out.println("当前线程" + Thread.currentThread().getId());
            int i = 10 / 4;
            System.out.println(i);
            return i;
        }, executor).handle((res,thr)->{
            if (res!=null){
                return res *2;
            }
            if (thr!=null){
                return 0;
            }
            return 1;
        });

在这里插入图片描述

4、线程串行化方法

在这里插入图片描述
thenApply 方法:当一个线程依赖另一个线程时,获取上一个任务返回的结果,并返回当前
任务的返回值。
thenAccept 方法:消费处理结果。接收任务的处理结果,并消费处理,无返回结果。
thenRun 方法:只要上面的任务执行完成,就开始执行 thenRun,只是处理完任务后,执行
thenRun 的后续操作
带有 Async 是多开一个线程,是异步执行的。同之前。
以上都要前置任务成功完成。

      //线程串行化
        /* 1、 thenRunAsync 不能获取上一步的执行结果
           2、 thenAcceptAsync 能接受上一步结果,但无返回值
           3、 thenApplyAsync能接受上一步结果,有返回值
        * */
 CompletableFuture<String> future = CompletableFuture.supplyAsync(() -> {
            System.out.println("当前线程" + Thread.currentThread().getId());
            int i = 10 / 4;
            System.out.println("运行结果"+i);
            return i;
        }, executor).thenApplyAsync(res -> {
            System.out.println("任务2启动了" + res);

            return "hello" + res;
        }, executor);

在这里插入图片描述

5、两任务组合 - 都要完成

在这里插入图片描述
两个任务必须都完成,触发该任务。

runAfterBoth:组合两个 future,不需要获取 future 的结果,只需两个 future 处理完任务后,
处理该任务。

CompletableFuture<Integer> future01 = CompletableFuture.supplyAsync(() -> {
            System.out.println("任务1线程" + Thread.currentThread().getId());
            int i = 10 / 4;
            System.out.println("任务1线程结束"+i);
            return i;
        }, executor);

        CompletableFuture<String> future02 = CompletableFuture.supplyAsync(() -> {
            System.out.println("任务2线程" + Thread.currentThread().getId());

            System.out.println("任务2线程结束");
            return "hello";
        }, executor);
        future01.runAfterBothAsync(future02,()->{
            System.out.println("任务3开始");
        },executor);

        System.out.println("方法结束");

在这里插入图片描述
thenAcceptBoth:组合两个 future,获取两个 future 任务的返回结果,然后处理任务,没有
返回值。

future01.thenAcceptBothAsync(future02,(f1,f2)->{
           System.out.println("任务3开始...之前的结果"+f1+f2);
       },executor);

在这里插入图片描述

thenCombine:组合两个 future,获取两个 future 的返回结果,并返回当前任务的返回值

 CompletableFuture<String> future = future01.thenCombineAsync(future02, (f1, f2) -> {
            return "组合处理任务1、2的结果" + f1 + f2 + "999";
        }, executor);

在这里插入图片描述

6、两任务组合 - 一个完成

在这里插入图片描述

runAfterEither:两个任务有一个执行完成,不需要获取 future 的结果,处理任务,也没有返
回值。

 future01.runAfterEitherAsync(future02,()->{
           System.out.println("任务3开始前的结果");
       },executor);

在这里插入图片描述
acceptEither:两个任务有一个执行完成,获取它的返回值,处理任务,没有新的返回值。

future01.acceptEitherAsync(future02,(res)->{
            System.out.println("任务3开始前的结果"+res);
        },executor);

在这里插入图片描述
applyToEither:两个任务有一个执行完成,获取它的返回值,处理任务并有新的返回值。

CompletableFuture<String> eitherAsync = future01.applyToEitherAsync(future02, (res) -> {
            System.out.println("任务3开始前结果" + res);
            return res.toString() + "--->" + "ke";
        }, executor);

        System.out.println("方法结束"+eitherAsync.get());

在这里插入图片描述

7、多任务组合

在这里插入图片描述

allOf:等待所有任务完成

  CompletableFuture<String> img = CompletableFuture.supplyAsync(() -> {
            System.out.println("查询商品信息");
            return "hello.jpg";
        },executor);
        CompletableFuture<String> attr = CompletableFuture.supplyAsync(() -> {
            System.out.println("查询属性信息");
            return "黑丝";
        },executor);
        CompletableFuture<String> desc = CompletableFuture.supplyAsync(() -> {
            try {
                Thread.sleep(3000);
                System.out.println("查询商品介绍");

            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            return "油量";
        },executor);
        CompletableFuture<Void> allOf = CompletableFuture.allOf(img, attr, desc);
        allOf.get();
        System.out.println("任务结束"+img.get()+attr.get()+desc.get());

在这里插入图片描述
anyOf:只要有一个任务完成

 CompletableFuture<Object> anyOf = CompletableFuture.anyOf(img, attr, desc);

在这里插入图片描述

### 大模型对齐微调DPO方法详解 #### DPO简介 直接偏好优化(Direct Preference Optimization, DPO)是一种用于改进大型语言模型行为的技术,该技术通过结合奖励模型训练和强化学习来提升训练效率稳定性[^1]。 #### 实现机制 DPO的核心在于它能够依据人类反馈调整模型输出的概率分布。具体来说,当给定一对候选响应时,DPO试图使更受偏好的那个选项具有更高的生成概率。这种方法不仅简化了传统强化学习所需的复杂环境设置,而且显著增强了模型对于多样化指令的理解能力和执行精度[^2]。 #### PAI平台上的实践指南 为了便于开发者实施这一先进理念,在PAI-QuickStart框架下提供了详尽的操作手册。这份文档覆盖了从环境配置直至完成整个微调流程所需的一切细节,包括但不限于数据准备、参数设定以及性能评估等方面的内容。尤其值得注意的是,针对阿里云最新发布的开源LLM——Qwen2系列,文中给出了具体的实例说明,使得即使是初次接触此类工作的用户也能顺利上手。 ```python from transformers import AutoModelForCausalLM, Trainer, TrainingArguments model_name_or_path = "qwen-model-name" tokenizer_name = model_name_or_path training_args = TrainingArguments( output_dir="./results", per_device_train_batch_size=8, num_train_epochs=3, ) trainer = Trainer( model_init=lambda: AutoModelForCausalLM.from_pretrained(model_name_or_path), args=training_args, train_dataset=train_dataset, ) # 假设已经定义好了train_dataset trainer.train() ``` 这段代码片段展示了如何使用Hugging Face库加载预训练模型并对其进行微调的过程。虽然这里展示的例子并不完全对应于DPO的具体实现方式,但它提供了一个基础模板供进一步定制化开发之用[^3]。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值