商城项目【尚品汇】08异步编排-01基础篇

news2024/10/7 4:24:13

文章目录

  • 1.线程的创建方式
    • 1.1继承Thread类,重写run方法
    • 1.2实现Runnable接口,重写run方法。
    • 1.3实现Callable接口,重新call方法
    • 1.4以上三种总结
    • 1.5使用线程池创建线程
      • 1.5.1线程池创建线程的方式
      • 1.5.2线程池的七大参数含义
      • 1.5.3线程池的工作流程
      • 1.5.4一个线程池core:7,max:20,queue:50。100个并发进来,怎么分配。
  • 2.CompletableFuture异步编排
    • 2.1创建异步对象方式
    • 2.2计算完成时回调方法
      • 2.1.1方法完成时的感知(方法一)
      • 2.1.2方法完成时的处理(方法二)
    • 2.3线程的串行化的方法
      • 2.3.1不能接收值且没有返回值
      • 2.3.2可以接收值但是没有返回值
      • 2.3.3可以接收值也可以返回值
    • 2.4两任务组合-一个完成即可
    • 2.5两任务组合-两个都要完成
    • 2.6多任务组合

1.线程的创建方式

1.1继承Thread类,重写run方法

package com.atguigu.gmall.product.thread;

import java.math.BigDecimal;

public class ThreadTest {
    public static void main(String[] args) {
        /**
         * 线程的创建方式
         * 1.继承Thread类
         */
        //开启线程
        System.out.println("主线程开始");
        Thread thread = new Thread01();
        thread.start();
        System.out.println("主线程完毕");
    }
    public static class Thread01 extends Thread{

        //创建线程方法一
        //通过继承Thread类重写run()方法,在run()方法中编写业务类
        @Override
        public void run() {
            System.out.println("通过继承Thread类,重写run()方法,创建线程"+Thread.currentThread().getId());
            BigDecimal bigDecimal = new BigDecimal(10);
            BigDecimal bigDecimal1 = new BigDecimal(3);
            BigDecimal divide = bigDecimal1.divide(bigDecimal);
            System.out.println("divide = " + divide);

        }
    }
}

结果
在这里插入图片描述

1.2实现Runnable接口,重写run方法。

package com.atguigu.gmall.product.thread;

import java.math.BigDecimal;

public class RunableTest {
    public static void main(String[] args) {
        /**
         * 创建线程的方法二:
         * 通过实现Runable接口,重新run方法,创建线程。
         */
        //开启线程
        System.out.println("主线程开始");
        Runable01 runable01 = new Runable01();
        Thread thread = new Thread(runable01);
        thread.start();
        System.out.println("主线程完毕");

    }
    public static class Runable01 implements Runnable{
        @Override
        public void run() {
            System.out.println("通过实现Runnable接口,重写run()方法,创建线程"+Thread.currentThread().getId());
            BigDecimal bigDecimal = new BigDecimal(10);
            BigDecimal bigDecimal1 = new BigDecimal(3);
            BigDecimal divide = bigDecimal1.divide(bigDecimal);
            System.out.println("divide = " + divide);
        }
    }
}

在这里插入图片描述

1.3实现Callable接口,重新call方法

package com.atguigu.gmall.product.thread;

import java.math.BigDecimal;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.Future;
import java.util.concurrent.FutureTask;

public class CallableTest {
    public static void main(String[] args) throws ExecutionException, InterruptedException {
        /**
         * 创建线程的方法三
         * 通过实现Callable<>接口,重写call方法,创建线程。可以获取到线程的返回值
         */
        System.out.println("主线程开始");
        FutureTask<String> futureTask = new FutureTask<String>(new Callable01());
        //开启线程
        new Thread(futureTask).start();
        //获取线程的返回值,会阻塞主线程
        System.out.println("主线程阻塞。。。。。。");
        String s = futureTask.get();
        System.out.println("线程的返回值s = " + s);
        System.out.println("主线程结束");
    }
    public static class Callable01 implements Callable<String>{
        @Override
        public String call() throws Exception {
            System.out.println("通过实现Callable<>接口,重写call方法,创建线程。可以获取到线程的返回值"+Thread.currentThread().getId());
            BigDecimal bigDecimal = new BigDecimal(10);
            BigDecimal bigDecimal1 = new BigDecimal(3);
            BigDecimal divide = bigDecimal1.divide(bigDecimal);
            System.out.println("divide = " + divide);
            return divide.toString();
        }
    }
}

在这里插入图片描述

1.4以上三种总结

1.开启线程的方式,Thread对象调用start方法。
2.以上三种只有第三种可以接收线程的返回值。

1.5使用线程池创建线程

1.5.1线程池创建线程的方式

        /**
         * 使用线程池创建线程
         */
        ThreadPoolExecutor executor = new ThreadPoolExecutor(
                10,
                20,
                10,
                TimeUnit.SECONDS,
                new ArrayBlockingQueue<>(1000),
                Executors.defaultThreadFactory(),
                new ThreadPoolExecutor.AbortPolicy()
                );

1.5.2线程池的七大参数含义

    /**
     * Creates a new {@code ThreadPoolExecutor} with the given initial
     * parameters.
     *
     * @param corePoolSize the number of threads to keep in the pool, even
     *        if they are idle, unless {@code allowCoreThreadTimeOut} is set
     * @param maximumPoolSize the maximum number of threads to allow in the
     *        pool
     * @param keepAliveTime when the number of threads is greater than
     *        the core, this is the maximum time that excess idle threads
     *        will wait for new tasks before terminating.
     * @param unit the time unit for the {@code keepAliveTime} argument
     * @param workQueue the queue to use for holding tasks before they are
     *        executed.  This queue will hold only the {@code Runnable}
     *        tasks submitted by the {@code execute} method.
     * @param threadFactory the factory to use when the executor
     *        creates a new thread
     * @param handler the handler to use when execution is blocked
     *        because the thread bounds and queue capacities are reached
     */
    public ThreadPoolExecutor(int corePoolSize,
                              int maximumPoolSize,
                              long keepAliveTime,
                              TimeUnit unit,
                              BlockingQueue<Runnable> workQueue,
                              ThreadFactory threadFactory,
                              RejectedExecutionHandler handler)
  • corePoolSize:核心的线程池数。也就是线程池一创建就有的。
  • maximumPoolSize:最大的线程池数。这个线程池可以创建的最大的线程池数。
  • keepAliveTime:当线程池中的线程数大于核心的线程池时,这些线程池执行完任务保持存活的时间。
  • unit:时间单位
  • workQueue:阻塞队列,当任务大于核心线程数时,任务就会放在阻塞队列中。
  • threadFactory:创建工厂。指定线程名。
  • handler:拒绝策略。当线程池中所有的线程都在执行任务,而且阻塞队列已经满了。那么来了任务就需要执行拒绝策略了。

1.5.3线程池的工作流程

1、创建线程池,会创建core线程。
2、当任务来了,core线程进行处理,若core不够,那么就会将任务放在workQueue中,当核心线程空闲下来,去workQueue阻塞队列中去任务。
3、若阻塞队列满了,线程池就去开启新的线程,直至线程池中的线程数达到maximumPoolSize最大线程池数。若新的线程空闲下来,过了过期时间,就会自动销毁。
4、若线程池中的线程池数达到了最大线程池数,而且还来了任务,那么就会使用拒绝策略进行处理。
5、所有的线程都是由指定的factory工厂创建的。

1.5.4一个线程池core:7,max:20,queue:50。100个并发进来,怎么分配。

首先:7个线程直接进行处理。
然后:进入队列50个。
再次:开启13个线程进行处理。
最后:70个被安排,30个交给阻塞队列。

2.CompletableFuture异步编排

2.1创建异步对象方式

   //方法一:
    public static CompletableFuture<Void> runAsync(Runnable runnable) {
        return asyncRunStage(asyncPool, runnable);
    }
   //方法二
    public static CompletableFuture<Void> runAsync(Runnable runnable,Executor executor) {
        return asyncRunStage(screenExecutor(executor), runnable);
    }
   //方法三
   public static <U> CompletableFuture<U> supplyAsync(Supplier<U>supplier) {
        return asyncSupplyStage(asyncPool, supplier);
    }
   //方法四
   public static <U> CompletableFuture<U> supplyAsync(Supplier<U> supplier,Executor executor) {
        return asyncSupplyStage(screenExecutor(executor), supplier);
    }

1.runXxx方法没有返回值,supplyXxx方法有返回值。
2.可以传入自定义的线程池,否则默认的线程池。
3.都不会接收返回值。

代码

package com.atguigu.gmall.product.completableFuture;

import rx.Completable;

import java.math.BigDecimal;
import java.util.concurrent.*;

public class Test {
    public static ExecutorService executors = Executors.newFixedThreadPool(10);
    public static void main(String[] args) throws ExecutionException, InterruptedException {
        /**
         * 1.创建异步对象
         */
        //CompletableFuture类中的静态方法
        long startMain = System.currentTimeMillis();
        System.out.println("主线程--开始");
        CompletableFuture<Void> future01 = CompletableFuture.runAsync(new Runnable01());
        CompletableFuture<Void> future02 = CompletableFuture.runAsync(() -> {
            long start02 = System.currentTimeMillis();
            System.out.println("id============================");
            long id = Thread.currentThread().getId();
            System.out.println("当前线程的id = " + id);
            BigDecimal a = new BigDecimal(10);
            BigDecimal b = new BigDecimal(2);
            BigDecimal divide = a.divide(b);
            System.out.println("运行结果divide = " + divide+"02-"+(System.currentTimeMillis() - start02));
        }, executors);
        CompletableFuture<String> future03 = CompletableFuture.supplyAsync(() -> {
            long start03 = System.currentTimeMillis();
            long id = Thread.currentThread().getId();
            System.out.println("id============================");
            System.out.println("当前线程的id = " + id);
            BigDecimal a = new BigDecimal(10);
            BigDecimal b = new BigDecimal(2);
            BigDecimal divide = a.divide(b);
            System.out.println("运行结果divide = " + divide+"03-"+(System.currentTimeMillis() - start03));
            return divide.toString();
        });
        System.out.println("获取返回结果future03.get() = " + future03.get());
        CompletableFuture<String> future04 = CompletableFuture.supplyAsync(() -> {
            long start04 = System.currentTimeMillis();
            long id = Thread.currentThread().getId();
            System.out.println("id============================");
            System.out.println("当前线程的id = " + id);
            BigDecimal a = new BigDecimal(10);
            BigDecimal b = new BigDecimal(2);
            BigDecimal divide = a.divide(b);
            System.out.println("运行结果divide = " + divide+"04-"+(System.currentTimeMillis() - start04));
            return divide.toString();
        },executors);
        System.out.println("获取返回结果future04 = " + future04.get());
        System.out.println("主线程--结束"+"Main用时"+(System.currentTimeMillis() - startMain));
    }

    public static class Runnable01 implements Runnable{
        @Override
        public void run() {
            long start01 = System.currentTimeMillis();
            System.out.println("id============================");
            long id = Thread.currentThread().getId();
            System.out.println("当前线程的id = " + id);
            BigDecimal a = new BigDecimal(10);
            BigDecimal b = new BigDecimal(2);
            BigDecimal divide = a.divide(b);
            System.out.println("运行结果divide = " + divide+"01-"+(System.currentTimeMillis() - start01));
        }
    }
    public static class Callable01 implements Callable<String> {
        @Override
        public String call() {
            System.out.println("id============================");
            long id = Thread.currentThread().getId();
            System.out.println("当前线程的id = " + id);
            BigDecimal a = new BigDecimal(10);
            BigDecimal b = new BigDecimal(2);
            BigDecimal divide = a.divide(b);
            System.out.println("运行结果divide = " + divide);
            return divide.toString();
        }
    }
}

2.2计算完成时回调方法

2.1.1方法完成时的感知(方法一)

    public CompletableFuture<T> whenComplete(
        BiConsumer<? super T, ? super Throwable> action) {
        return uniWhenCompleteStage(null, action);
    }

    public CompletableFuture<T> whenCompleteAsync(
        BiConsumer<? super T, ? super Throwable> action) {
        return uniWhenCompleteStage(asyncPool, action);
    }

    public CompletableFuture<T> whenCompleteAsync(
        BiConsumer<? super T, ? super Throwable> action, Executor executor) {
        return uniWhenCompleteStage(screenExecutor(executor), action);
    }
        public CompletableFuture<T> exceptionally(
        Function<Throwable, ? extends T> fn) {
        return uniExceptionallyStage(fn);
    }

whenComplete 可以处理正常结果但是不能返回结果、感知异常但是不能处理异常。这个方法不可以进行返回值
exceptionally可以感知异常并且修改返回值进行返回。

whenComplete 和 whenCompleteAsync 的区别:
whenComplete:是执行当前任务的线程执行继续执行 whenComplete 的任务。
whenCompleteAsync:是执行把 whenCompleteAsync 这个任务继续提交给线程池来进行执行。
方法不以 Async 结尾,意味着 Action 使用相同的线程执行,而 Async 可能会使用其他线程执行(如果是使用相同的线程池,也可能会被同一个线程选中执行)
代码示例

package com.atguigu.gmall.product.completableFuture;

import java.math.BigDecimal;
import java.util.concurrent.*;

public class Test02 {
    public static ExecutorService executors = Executors.newFixedThreadPool(10);
    public static void main(String[] args) throws ExecutionException, InterruptedException {

        CompletableFuture<String> exceptionally = CompletableFuture.supplyAsync(() -> {
            int i = 10/0;
            return "a";
        }).whenCompleteAsync((res, exception) -> {
            //尽可以感到异常,不可以修改返回结果
            System.out.println("输出返回结果" + res);

        }, executors).exceptionally((exception -> {
            //可以感到异常,并且修改返回结果
            return "b";
        }));
        System.out.println("获取返回结果:" + exceptionally.get());

    }

    public static class Runnable01 implements Runnable{
        @Override
        public void run() {
            long start01 = System.currentTimeMillis();
            System.out.println("id============================");
            long id = Thread.currentThread().getId();
            System.out.println("当前线程的id = " + id);
            BigDecimal a = new BigDecimal(10);
            BigDecimal b = new BigDecimal(2);
            BigDecimal divide = a.divide(b);
            System.out.println("运行结果divide = " + divide+"01-"+(System.currentTimeMillis() - start01));
        }
    }
    public static class Callable01 implements Callable<String> {
        @Override
        public String call() {
            System.out.println("id============================");
            long id = Thread.currentThread().getId();
            System.out.println("当前线程的id = " + id);
            BigDecimal a = new BigDecimal(10);
            BigDecimal b = new BigDecimal(2);
            BigDecimal divide = a.divide(b);
            System.out.println("运行结果divide = " + divide);
            return divide.toString();
        }
    }
}

2.1.2方法完成时的处理(方法二)

    public <U> CompletableFuture<U> handle(
        BiFunction<? super T, Throwable, ? extends U> fn) {
        return uniHandleStage(null, fn);
    }

    public <U> CompletableFuture<U> handleAsync(
        BiFunction<? super T, Throwable, ? extends U> fn) {
        return uniHandleStage(asyncPool, fn);
    }

    public <U> CompletableFuture<U> handleAsync(
        BiFunction<? super T, Throwable, ? extends U> fn, Executor executor) {
        return uniHandleStage(screenExecutor(executor), fn);
    }

不仅可以处理正常结果而且可以处理异常
不仅可以接收值,而且可以返回处理结果

代码实例

package com.atguigu.gmall.product.completableFuture;

import java.math.BigDecimal;
import java.util.concurrent.*;

public class Test02 {
    public static ExecutorService executors = Executors.newFixedThreadPool(10);
    public static void main(String[] args) throws ExecutionException, InterruptedException {

        CompletableFuture<String> exceptionally = CompletableFuture.supplyAsync(() -> {
            int i = 10/0;
            return "a";
        }).handleAsync((res,exception) -> {
            //不仅可以接收参数,而且可以返回结果
            if (res != null){
                return "值"+res;
            }
            if (exception != null){
                return "异常"+exception.getMessage();
            }
            return "0";
        },executors);
        System.out.println("获取返回结果:" + exceptionally.get());

    }

    public static class Runnable01 implements Runnable{
        @Override
        public void run() {
            long start01 = System.currentTimeMillis();
            System.out.println("id============================");
            long id = Thread.currentThread().getId();
            System.out.println("当前线程的id = " + id);
            BigDecimal a = new BigDecimal(10);
            BigDecimal b = new BigDecimal(2);
            BigDecimal divide = a.divide(b);
            System.out.println("运行结果divide = " + divide+"01-"+(System.currentTimeMillis() - start01));
        }
    }
    public static class Callable01 implements Callable<String> {
        @Override
        public String call() {
            System.out.println("id============================");
            long id = Thread.currentThread().getId();
            System.out.println("当前线程的id = " + id);
            BigDecimal a = new BigDecimal(10);
            BigDecimal b = new BigDecimal(2);
            BigDecimal divide = a.divide(b);
            System.out.println("运行结果divide = " + divide);
            return divide.toString();
        }
    }
}

2.3线程的串行化的方法

2.3.1不能接收值且没有返回值

thenRun方法:只要上面的任务执行完成,就开始执行thenRun,只是处理完任务后,执行 thenRun的后续操作

    public CompletableFuture<Void> thenRun(Runnable action) {
        return uniRunStage(null, action);
    }

    public CompletableFuture<Void> thenRunAsync(Runnable action) {
        return uniRunStage(asyncPool, action);
    }

    public CompletableFuture<Void> thenRunAsync(Runnable action,
                                                Executor executor) {
        return uniRunStage(screenExecutor(executor), action);
    }

代码示例

package com.atguigu.gmall.product.completableFuture;

import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

public class Test03 {
    public static ExecutorService excutor =Executors.newFixedThreadPool(10);
    public static void main(String[] args) throws ExecutionException, InterruptedException {

        CompletableFuture<Void> future01 = CompletableFuture.supplyAsync(() -> {
            int i = 0;
            System.out.println("i = " + i);
            return i;
        }).thenRunAsync(() -> {
            int j = 0;
            System.out.println("j = " + j);
        });
        Void unused = future01.get();
        System.out.println("unused = " + unused);
    }
}

2.3.2可以接收值但是没有返回值

thenAccept方法:消费处理结果。接收任务的处理结果,并消费处理,无返回结果。

    public CompletableFuture<Void> thenAccept(Consumer<? super T> action) {
        return uniAcceptStage(null, action);
    }

    public CompletableFuture<Void> thenAcceptAsync(Consumer<? super T> action) {
        return uniAcceptStage(asyncPool, action);
    }

    public CompletableFuture<Void> thenAcceptAsync(Consumer<? super T> action,
                                                   Executor executor) {
        return uniAcceptStage(screenExecutor(executor), action);
    }

2.3.3可以接收值也可以返回值

thenApply 方法:当一个线程依赖另一个线程时,获取上一个任务返回的结果,并返回当前任务的返回值。

    public <U> CompletableFuture<U> thenApply(
        Function<? super T,? extends U> fn) {
        return uniApplyStage(null, fn);
    }

    public <U> CompletableFuture<U> thenApplyAsync(
        Function<? super T,? extends U> fn) {
        return uniApplyStage(asyncPool, fn);
    }

    public <U> CompletableFuture<U> thenApplyAsync(
        Function<? super T,? extends U> fn, Executor executor) {
        return uniApplyStage(screenExecutor(executor), fn);
    }

代码示例

package com.atguigu.gmall.product.completableFuture;

import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

public class Test03 {
    public static ExecutorService excutor =Executors.newFixedThreadPool(10);
    public static void main(String[] args) throws ExecutionException, InterruptedException {

        CompletableFuture<Integer> future03 = CompletableFuture.supplyAsync(() -> {
            int i = 0;
            System.out.println("i = " + i);
            return i;
        }).thenApplyAsync((res) -> {
            res++;
            return res;
        });
        Integer integer = future03.get();
        System.out.println("integer = " + integer);
    }
}

带有Async默认是异步执行的。这里所谓的异步指的是不在当前线程内执行。

Function<? super T,? extends U>
T:上一个任务返回结果的类型
U:当前任务的返回值类型

2.4两任务组合-一个完成即可

2.5两任务组合-两个都要完成

2.6多任务组合

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1806212.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

html写一个table表

HTML代码&#xff1a; <div class"table_box w-full"><div class"title_top">XX表</div><div class"title_btm">(<input class"input input_1" type"text">xxxx)</div><table class…

Jenkins构建打包部署前端Vue项目至Nginx

一. 安装jenkins 基于DockerJenkins实现自动部署SpringBootMaven项目-CSDN博客 二. 安装NodeJs插件并配置 显示上面两行则表示安装成功, 然后回到首页, 点击’系统管理’->‘全局工具配置’: 配置node.js 三. 创建jenkins项目 1、创建项目 2、配置gitee 3、配置源码 4、…

kafka如何保证消息不丢失

Kafka发送消息是异步发送的&#xff0c;所以我们不知道消息是否发送成功&#xff0c;所以会可能造成消息丢失。而且Kafka架构是由生产者-服务器端-消费者三种组成部分构成的。要保证消息不丢失&#xff0c;那么主要有三种解决方法。 生产者(producer)端处理 生产者默认发送消息…

qmt量化交易策略小白学习笔记第16期【qmt编程之获取北向南向资金(沪港通,深港通和港股通)】

qmt编程之获取北向南向资金 qmt更加详细的教程方法&#xff0c;会持续慢慢梳理。 也可找寻博主的历史文章&#xff0c;搜索关键词查看解决方案 &#xff01; 北向南向资金&#xff08;沪港通&#xff0c;深港通和港股通&#xff09; #北向南向资金交易日历 获取交易日列表…

Cartographer学习笔记

Cartographer 是一个跨多个平台和传感器配置提供 2D 和 3D 实时同步定位和地图绘制 (SLAM) 的系统。 1. 文件关系 2. 代码框架 common: 定义了基本数据结构和一些工具的使用接口。例如&#xff0c;四舍五入取整的函数、时间转化相关的一些函数、数值计算的函数、互斥锁工具等…

gcc源码分析 词法和语法分析

gcc源码分析 词法和语法分析 一、输入参数相关1、命令行到gcc二、词法与语法分析1、词法分析1.1 struct cpp_reader1.2 struct tokenrun/struct cpp_token/lookahead字段1.3 struct ht2.1 语法符号相关的结构体c_token定义如下:2.2在语法分析中实际上有多个API组成了其接口函数…

【Python】Selenium基础入门

Selenium基础入门 一、Selenium简介二、Selenium的安装三、Selenium的使用1.访问web网站2.元素定位根据标签 id 获取元素根据标签 name 属性的值获取元素根据 Xpath 语句获取元素根据标签名获取元素根据CSS选择器获取元素根据标签的文本获取元素&#xff08;精确定位&#xff0…

JVM学习-监控工具(一)

使用数据说明问题&#xff0c;使用知识分析问题&#xff0c;使用工具处理问题 无监控&#xff0c;不调优&#xff01; 命令行工具 在JDK安装目录下&#xff0c;可以查看到相应的命令行工具&#xff0c;如下图 jps(Java Process Status) 显示指定系统内所有的Hotpot虚拟机…

【算法刷题 | 动态规划08】6.9(单词拆分、打家劫舍、打家劫舍||)

文章目录 21.单词拆分21.1题目21.2解法&#xff1a;动规21.2.1动规思路21.2.2代码实现 22.打家劫舍22.1题目22.2解法&#xff1a;动规22.2.1动规思路22.2.2代码实现 23.打家劫舍||23.1题目23.2解法&#xff1a;动规23.2.1动规思路23.2.2代码实现 21.单词拆分 21.1题目 给你一…

如何获取当前dll或exe模块所在路径?

有时我们需要在当前运行的dll或exe模块中去动态加载当前模块同路径中的另一个库&#xff0c;或者启动当前模块同路径中的另一个exe程序&#xff0c;一般需要获取当前模块的路径&#xff0c;然后去构造同路径下目标模块的绝对路径&#xff0c;然后通过该绝对路径去加载或启动该目…

SpringBoot集成缓存功能

1. 缓存规范 Java Caching定义了五个核心接口&#xff0c;分别是&#xff1a;CachingProvider、CacheManager、Cache、Entry和Expiry。 CachingProvider&#xff1a;定义了创建、配置、获取、管理和控制多个CacheManager。一个应用可以在运行期访问多个CachingProvider。CacheM…

URL的编码解码(一),仅针对ASCII码字符

用十六进制对特定字符编码&#xff0c;利用百分号标识搜索字符串解码十六进制字符。 (笔记模板由python脚本于2024年06月09日 18:05:25创建&#xff0c;本篇笔记适合喜好探寻URL的coder翻阅) 【学习的细节是欢悦的历程】 Python 官网&#xff1a;https://www.python.org/ Free…

基于深度学习的中文语音识别模型(支持wav、mp4、m4a等所有格式音频上传)【已开源】

基于深度学习的中文语音识别模型&#xff08;支持wav、mp4、m4a等所有格式音频上传&#xff09; 前言 该开源项目旨在提供一个能够自动检测并识别中文语音的模型&#xff0c;支持wav、mp4、m4a等格式的音频文件上传。无论是从录音设备中获取的wav文件&#xff0c;还是从视频中…

Kingshard:MySQL代理,释放数据库潜能

Kingshard&#xff1a; 简化数据库管理&#xff0c;提升性能极限。- 精选真开源&#xff0c;释放新价值。 概览 kingshard是一个由Go开发的高性能MySQL Proxy项目&#xff0c;专为简化数据库管理和提升查询性能而设计。kingshard在满足基本的读写分离的功能上&#xff0c;致力…

Llama模型家族之Stanford NLP ReFT源代码探索 (四)Pyvene论文学习

LlaMA 3 系列博客 基于 LlaMA 3 LangGraph 在windows本地部署大模型 &#xff08;一&#xff09; 基于 LlaMA 3 LangGraph 在windows本地部署大模型 &#xff08;二&#xff09; 基于 LlaMA 3 LangGraph 在windows本地部署大模型 &#xff08;三&#xff09; 基于 LlaMA…

【react】react项目支持鼠标拖拽的边框改变元素宽度的组件

目录 安装使用方法示例Props 属性方法示例代码调整兄弟div的宽度 re-resizable github地址 安装 $ npm install --save re-resizable这将安装re-resizable库并将其保存为项目的依赖项。 使用方法 re-resizable 提供了一个 <Resizable> 组件&#xff0c;它可以包裹任何…

[hddm]python模块hddm安装后测试代码

测试环境&#xff1a; hddm0.8.0 测试文件test.csv subj_idx,stim,rt,response,theta,dbs,conf 0,LL,1.21,1.0,0.65627512226100004,1,HC 0,WL,1.6299999999999999,1.0,-0.32788867166199998,1,LC 0,WW,1.03,1.0,-0.480284512399,1,HC 0,WL,2.77,1.0,1.9274273452399999,1,L…

使用 Scapy 库编写 TCP 劫持攻击脚本

一、介绍 TCP劫持攻击&#xff08;TCP Hijacking&#xff09;&#xff0c;也称为会话劫持&#xff0c;是一种攻击方式&#xff0c;攻击者在合法用户与服务器之间的通信过程中插入或劫持数据包&#xff0c;从而控制通信会话。通过TCP劫持&#xff0c;攻击者可以获取敏感信息、执…

网络基础-IP协议

文章目录 前言一、IP报文二、IP报文分片重组IP分片IP分片示例MTUping 命令可以验证MTU大小Windows系统&#xff1a;Linux系统: 前言 基础不牢&#xff0c;地动山摇&#xff0c;本节我们详细介绍IP协议的内容。 一、IP报文 第一行&#xff1a; 4位版本号指定IP协议的版本&#…

C语言详解(联合和枚举)

Hi~&#xff01;这里是奋斗的小羊&#xff0c;很荣幸您能阅读我的文章&#xff0c;诚请评论指点&#xff0c;欢迎欢迎 ~~ &#x1f4a5;个人主页&#xff1a;奋斗的小羊 &#x1f4a5;所属专栏&#xff1a;C语言 &#x1f680;本系列文章为个人学习笔记&#xff0c;在这里撰写…