Java --- JUC的CompletableFuture的使用

news2024/11/17 14:52:24

目录

一、Future接口

二、Future接口的功能

三、FutureTask

四、CompletableFuture背景及使用

4.1、CompletionStage

 4.2、CompletableFuture

4.3、四个静态方法 

4.4、减少阻塞和轮询

4.5、使用CompletableFuture完成电商大比价

 五、CompletableFuture常用API

5.1、获取结果

5.2、主动触发计算

5.3、对计算结果进行处理

5.4、对计算结果进行消费

5.5、对计算速度进行选用

5.6、对计算结果合并


一、Future接口

Future接口(FutureTask实现类)定义了操作异步任务执行一些方法,如获取异步任务的执行结果,取消任务的执行,判断任务是否被取消,判断任务执行是否完毕等。

如:主线程让一个子线程去执行任务,子线程在执行过程中过于耗时,启动子线程开始执行任务后,主线程就去做其他事情,当主线程将需要其他实现做完后,等一会再去获取子任务系统的执行结果或变更的任务状态。

小结:Future接口可以为主线程开一个分支任务,专门为主线程处理耗时和费力的复杂业务。

二、Future接口的功能

Future是Java5新加的一个接口,它提供了一种异步并行计算功能。如果主线程需要执行一个很耗时的计算任务,我们可以通过Future把这个任务放到异步线程中执行。主线程继续处理其他任务或者先行结束,再通过Future获取计算结果。

目的:异步多线程任务执行且返回结果,三个特点:多线程、有返回、异步任务

三、FutureTask

架构图 :

 使用并实现异步任务:

public class FutureTest {
    public static void main(String[] args) throws ExecutionException, InterruptedException {
        FutureTask<String> futureTask = new FutureTask<>(new MyThread());
        Thread t1 = new Thread(futureTask,"t1");
        t1.start();
        //获取结果
        System.out.println(futureTask.get());
    }
}

class MyThread implements Callable<String>{

    @Override
    public String call() throws Exception {
        System.out.println("调用call()。。。。");
        return "hello year";
    }
}

优点:future+线程池异步多线程任务配合,能显著提高程序的执行效率

public class FutureTaskPoolTest {
    public static void main(String[] args) throws ExecutionException, InterruptedException {
        //创建线程池
        ExecutorService executorService = Executors.newFixedThreadPool(3);
        long startTime = System.currentTimeMillis();
        FutureTask<String > task1 = new FutureTask<String>(() -> {
            try {
                TimeUnit.MILLISECONDS.sleep(500);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            return "task1 over";
        });
        executorService.submit(task1);
        FutureTask<String > task2 = new FutureTask<String>(() -> {
            try {
                TimeUnit.MILLISECONDS.sleep(300);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            return "task2 over";
        });
        executorService.submit(task2);
        System.out.println(task1.get());
        System.out.println(task2.get());
        FutureTask<String > task3 = new FutureTask<String>(() -> {
            try {
                TimeUnit.MILLISECONDS.sleep(200);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            return "task3 over";
        });
        executorService.shutdown();
        long endTime = System.currentTimeMillis();
        System.out.println("耗时:"+(endTime - startTime)+"毫秒");//耗时:563毫秒
        System.out.println(Thread.currentThread().getName()+"\t .....end");
    }
    public static void m(){
        long startTime = System.currentTimeMillis();
        try {
            TimeUnit.MILLISECONDS.sleep(500);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        try {
            TimeUnit.MILLISECONDS.sleep(300);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        try {
            TimeUnit.MILLISECONDS.sleep(200);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        long endTime = System.currentTimeMillis();
        System.out.println("耗时:"+(endTime - startTime)+"毫秒");//耗时:1022毫秒
        System.out.println(Thread.currentThread().getName()+"\t .....end");
    }
}

 缺点:get()阻塞,一旦调用get()方法求结果,如果计算没有完成很容易导致程序阻塞。

public class FutureTask01 {
    public static void main(String[] args) throws ExecutionException, InterruptedException, TimeoutException {
        FutureTask<String> task = new FutureTask<String>(() -> {
            System.out.println(Thread.currentThread().getName()+"\t ...start");
            TimeUnit.SECONDS.sleep(5);
           return "task ok";
        });
        Thread thread = new Thread(task,"task");
        thread.start();
        System.out.println(Thread.currentThread().getName()+"\t ...其他任务");
        //System.out.println(task.get());
        //也可以设置超时不继续等
        System.out.println(task.get(4,TimeUnit.SECONDS));
    }
}

isDone()轮询:轮询的方式会耗费无谓的CPU资源,而且也不见得能及时地得到计算结果。如果想要异步获取结果,通常都会以轮询地方式去获取结果尽量不要阻塞。

public class FutureTask01 {
    public static void main(String[] args) throws ExecutionException, InterruptedException, TimeoutException {
        FutureTask<String> task = new FutureTask<String>(() -> {
            System.out.println(Thread.currentThread().getName()+"\t ...start");
            TimeUnit.SECONDS.sleep(5);
           return "task ok";
        });
        Thread thread = new Thread(task,"task");
        thread.start();
        System.out.println(Thread.currentThread().getName()+"\t ...其他任务");
        //System.out.println(task.get());
        //也可以设置超时不继续等
        //System.out.println(task.get(4,TimeUnit.SECONDS));
        while (true){
            if (task.isDone()){
                System.out.println(task.get());
                break;
            }else {
                TimeUnit.MILLISECONDS.sleep(500);
                System.out.println("正在拼命处理中。。。");
            }
        }
    }
}

 总结:Future对于结果地获取不是很友好,只能通过阻塞或轮询地方式获取结果

四、CompletableFuture背景及使用

get()方法在Future计算完成之前一直处于阻塞状态下,isDone()方法容易耗费CPU资源,对于真正地异步处理我们希望是可以通过传入回调函数,在Future结束时自动调用该回调函数,这样,我们就不用等待结果。

阻塞的方式和异步编程的设计理念违背,而轮询的方式会耗费无谓的CPU资源。因此,JDK8设计出CompletableFuture。

CompletableFuture提供了一种观察者模式类似的机制,可以让任务执行完成后通知监听的一方 

类架构图: 

4.1、CompletionStage

代表异步计算过程中的某一个阶段,一个阶段完成后可能会触发另外一个阶段,有些类似Linux系统的管道分割符传递参数。

一个阶段的计算执行可以是一个Future,Consumer,或者Runnable。

一个阶段的执行可能是被单个阶段的完成触发,也可能是由多个阶段一起触发。

 4.2、CompletableFuture

1、在Java8中,CompletableFuture提供了非常强大的Future的扩展功能,可以帮助我们简化异步编程的复杂性,并且提供了函数式编程的能力,可以通过回调的方式处理计算结果,也提供了转换和组合CompletableFuture的方法。

2、它可能代表一个明确完成的Future,也可能代表一个完成阶段(CompletionStage),它支持在计算完成以后触发一些函数和执行某些动作。

3、它实现了Future和CompletionStage接口。

4.3、四个静态方法 

runAsync无返回值:

public static CompletableFuture<Void> runAsync(Runnable runnable)
public static CompletableFuture<Void> runAsync(Runnable runnable,Executor executor)
public class CompletableFutureTest {
    public static void main(String[] args) throws ExecutionException, InterruptedException {
        CompletableFuture<Void> completableFuture = CompletableFuture.runAsync(() -> {
            System.out.println(Thread.currentThread().getName());
            try {
                TimeUnit.SECONDS.sleep(2);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        });
        System.out.println(completableFuture.get());
    }
}

 

public class CompletableFutureTest {
    public static void main(String[] args) throws ExecutionException, InterruptedException {
        ExecutorService pool = Executors.newFixedThreadPool(3);
        CompletableFuture<Void> completableFuture = CompletableFuture.runAsync(() -> {
            System.out.println(Thread.currentThread().getName());
            try {
                TimeUnit.SECONDS.sleep(2);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        },pool);
        System.out.println(completableFuture.get());
        pool.shutdown();
    }
}

 

 supplyAsync有返回值:

public static <U> CompletableFuture<U> supplyAsync(Supplier<U> supplier)
public static <U> CompletableFuture<U> supplyAsync(Supplier<U> supplier,Executor executor)
public class CompletableFutureTest {
    public static void main(String[] args) throws ExecutionException, InterruptedException {
//        ExecutorService pool = Executors.newFixedThreadPool(3);
        CompletableFuture<String> completableFuture = CompletableFuture.supplyAsync(() -> {
            System.out.println(Thread.currentThread().getName());
            try {
                TimeUnit.SECONDS.sleep(2);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
           return "future ok";
        });
        System.out.println(completableFuture.get());
    }
}

 

public class CompletableFutureTest {
    public static void main(String[] args) throws ExecutionException, InterruptedException {
        ExecutorService pool = Executors.newFixedThreadPool(3);
        CompletableFuture<String> completableFuture = CompletableFuture.supplyAsync(() -> {
            System.out.println(Thread.currentThread().getName());
            try {
                TimeUnit.SECONDS.sleep(2);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
           return "future ok";
        },pool);
        System.out.println(completableFuture.get());
        pool.shutdown();
    }
}

 

 上述Executor executor参数:没有指定Executor的方法,直接使用默认的ForkJoinPool.commonPool()作为它的线程池执行异步代码。如果指定线程池,则使用我们自定义的或者特别指定的线程池执行异步代码。

4.4、减少阻塞和轮询

从Java8开始引进了CompletableFuture,它是Future的功能增强版,减少阻塞和轮询可以传入回调对象,当异步任务完成或者发生异常时,自动调用回调对象的回调方法。

public class CompletableFutureDemo {
    public static void main(String[] args) {
        //线程池建议自己创建
        ExecutorService pool = Executors.newFixedThreadPool(3);
        try {
            CompletableFuture.supplyAsync(() -> {
                System.out.println(Thread.currentThread().getName());
                int result = ThreadLocalRandom.current().nextInt(20);
                if (result > 5){
                    int i = 1/0;
                }
                try {
                    TimeUnit.SECONDS.sleep(1);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                System.out.println("计算结果需要1秒" + result);
                return result;
            },pool).whenComplete((v,e) ->{
                if (e == null){
                    System.out.println("----计算完成的值为:" + v);
                }
            }).exceptionally(e ->{
                e.printStackTrace();
                System.out.println("异常情况:" + e.getCause()+ "\t" + e.getMessage());
                return null;
            });
            System.out.println(Thread.currentThread().getName() + "先去执行别的任务");
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            pool.shutdown();
        }

        //主线程不要立刻结束,不然CompletableFuture使用的线程池会立刻关闭掉,这里可先暂停3秒
//        try {
//            TimeUnit.SECONDS.sleep(3);
//        } catch (InterruptedException e) {
//            e.printStackTrace();
//        }
    }
}

优点:1、异步任务结束时,会自动回调某个对象的方法。2、主线程设置好回调后,不再关心异步任务的执行,异步任务之间可以顺序执行。3、异步任务出错时,会自动回调某个对象的方法。

4.5、使用CompletableFuture完成电商大比价

public class CompletableFutureMall {
    static List<NetMall> list = Arrays.asList(
      new NetMall("jd"),
      new NetMall("taobao"),
      new NetMall("dangdang")
    );
    //一家家搜索
    public static List<String> getPrice(List<NetMall> list,String productName){
       return list
               .stream()
               .map(netMall ->
                       String.format(productName + " in %s price is %.2f",
                               netMall.getNetMallName(),
                               netMall.calcPrice(productName)))
               .collect(Collectors.toList());
    }
    //异步搜索
    public static List<String> getPriceByCompletableFuture(List<NetMall> list,String productName){
        return list.stream().map(netMall ->
                CompletableFuture.supplyAsync(() ->String.format(productName + " in %s price is %.2f",
                netMall.getNetMallName(),
                netMall.calcPrice(productName))))
                .collect(Collectors.toList())
                .stream()
                .map(s -> s.join())
                .collect(Collectors.toList());
    }
    public static void main(String[] args) {
        long start = System.currentTimeMillis();
        List<String> stringList = getPrice(list, "java");
        for (String element:stringList) {
            System.out.println(element);
        }
        long end = System.currentTimeMillis();
        System.out.println("耗时:" + (end - start) + "毫秒");

        System.out.println("改进后的方法:");
        long start1 = System.currentTimeMillis();
        List<String> strings = getPriceByCompletableFuture(list, "java");
        for (String element:strings) {
            System.out.println(element);
        }
        long end1 = System.currentTimeMillis();
        System.out.println("耗时:" + (end1 - start1) + "毫秒");
    }
}

class NetMall{
    private String netMallName;

    public String getNetMallName() {
        return netMallName;
    }

    public NetMall(String netMallName) {
        this.netMallName = netMallName;
    }
    public double calcPrice(String productName){
        try {
            TimeUnit.SECONDS.sleep(1);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        return ThreadLocalRandom.current().nextDouble() * 2 + productName.charAt(0);
    }
}

 五、CompletableFuture常用API

5.1、获取结果

public class CompletableFutureAPI {
    public static void main(String[] args) throws ExecutionException, InterruptedException, TimeoutException {
        CompletableFuture<String> completableFuture = CompletableFuture.supplyAsync(() -> {
            try {
                TimeUnit.SECONDS.sleep(1);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            return "计算完成";
        });
       // System.out.println(completableFuture.get());//调用就必须给值
//        System.out.println(completableFuture.get(0,TimeUnit.SECONDS));//调用后,只获得等待时间内的值
//        System.out.println(completableFuture.join());//与get方法一样
        System.out.println(completableFuture.getNow("替代值111"));//立即获取结果不阻塞,计算完,返回计算完的值,否则就返回替代值

    }
}

5.2、主动触发计算

public class CompletableFutureAPI {
    public static void main(String[] args) {
        CompletableFuture<String> completableFuture = CompletableFuture.supplyAsync(() -> {
            try {
                TimeUnit.SECONDS.sleep(2);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            return "计算完成";
        });
        try {
            TimeUnit.SECONDS.sleep(1);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        //当调用completableFuture.join()被阻塞时,complete方法返回true,并将里面的值赋给join方法并返回
        System.out.println(completableFuture.complete("yyds" )+"\t" + completableFuture.join());

    }
}

5.3、对计算结果进行处理

thenApply:计算结果存在依赖关系,这两个线程串行化

public class CompletableFutureAPI2 {
    public static void main(String[] args) {
        ExecutorService pool = Executors.newFixedThreadPool(3);
        CompletableFuture<Integer> completableFuture = CompletableFuture.supplyAsync(() -> {
            try {
                TimeUnit.SECONDS.sleep(1);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println("111");
            return 1;
        },pool).thenApply(f ->{
            System.out.println("222");
            return f + 2;
        }).thenApply(f ->{
            System.out.println("333");
            return f + 3;
        }).whenComplete((v,e) ->{
            if (e == null){
                System.out.println("计算结果:" + v);
            }
        }).exceptionally(e -> {
            e.printStackTrace();
            System.out.println(e.getMessage());
            return null;
        });
        pool.shutdown();
    }
}

由于存在依赖关系,当前步骤有异常的话就叫停。

public class CompletableFutureAPI2 {
    public static void main(String[] args) {
        ExecutorService pool = Executors.newFixedThreadPool(3);
        CompletableFuture<Integer> completableFuture = CompletableFuture.supplyAsync(() -> {
            try {
                TimeUnit.SECONDS.sleep(1);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println("111");
            return 1;
        },pool).handle((f,e) ->{
            System.out.println("222");
            int i = 1/0;
            return f + 2;
        }).handle((f,e) ->{
            System.out.println("333");
            return f + 3;
        }).whenComplete((v,e) ->{
            if (e == null){
                System.out.println("计算结果:" + v);
            }
        }).exceptionally(e -> {
            e.printStackTrace();
            System.out.println(e.getMessage());
            return null;
        });
        pool.shutdown();
    }
}

有异常也可以往下一步走,根据带的异常参数可以进。

5.4、对计算结果进行消费

public class CompletableFutureAPI3 {
    public static void main(String[] args) {
        System.out.println(CompletableFuture.supplyAsync(() -> "resultA").thenRun(() -> {
        }).join());
        System.out.println(CompletableFuture.supplyAsync(() -> "resultA").thenAccept(r -> System.out.println(r)).join());
        System.out.println(CompletableFuture.supplyAsync(() -> "resultA").thenApply(r -> r+"resultB").join());

    }
}

CompletableFuture与线程池的选择

public class CompletableFutureAPI4 {
    public static void main(String[] args) throws InterruptedException {
        ExecutorService pool = Executors.newFixedThreadPool(6);
        try {
            CompletableFuture.supplyAsync(() ->{
                try {
                    TimeUnit.MILLISECONDS.sleep(10);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                System.out.println("1号任务\t"+Thread.currentThread().getName());
                return "aa";
            },pool).thenRunAsync(()->{
                try {
                    TimeUnit.MILLISECONDS.sleep(20);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                System.out.println("2号任务\t"+Thread.currentThread().getName());
            }).thenRun(()->{
                try {
                    TimeUnit.MILLISECONDS.sleep(20);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                System.out.println("3号任务\t"+Thread.currentThread().getName());
            }).thenRun(()->{
                try {
                    TimeUnit.MILLISECONDS.sleep(10);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                System.out.println("4号任务\t"+Thread.currentThread().getName());
            });
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            pool.shutdown();
        }
        TimeUnit.SECONDS.sleep(1);
    }
}

1、没有传入自定义线程池,都使用默认线程池。

2、传入了一个自定义线程池,当执行第一个任务的时候,传入一个自定义线程池:调用thenRun方法执行第二个任务时,则第二个任务和第一个任务是共用一个线程池。调用thenRunAsync执行第二个任务时,则第一个任务使用的是自己传入的线程池,第二个任务使用是默认线程池。

3、有可能系统处理太快,系统优化切换原则,直接使用main线程处理。

5.5、对计算速度进行选用

public class CompletableFutureAPI5 {
    public static void main(String[] args) {
        CompletableFuture<String> futureA = CompletableFuture.supplyAsync(() -> {
            try {
                TimeUnit.SECONDS.sleep(2);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            return "A完成了";
        });
        CompletableFuture<String> futureB = CompletableFuture.supplyAsync(() -> {
            try {
                TimeUnit.SECONDS.sleep(3);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            return "B完成了";
        });
        CompletableFuture<String> completableFuture = futureA.applyToEither(futureB, f -> {
            return f + "领先";
        });
        System.out.println(Thread.currentThread().getName() + "\t" + completableFuture.join());

    }
}

5.6、对计算结果合并

public class CompletableFutureAPI6 {
    public static void main(String[] args) {
        CompletableFuture<Integer> future1 = CompletableFuture.supplyAsync(() -> {
            try {
                TimeUnit.SECONDS.sleep(1);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            return 10;
        });
        CompletableFuture<Integer> future2 = CompletableFuture.supplyAsync(() -> {
            try {
                TimeUnit.SECONDS.sleep(2);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            return 20;
        });
        CompletableFuture<Integer> result = future1.thenCombine(future2, (x, y) -> {
            System.out.println("两个结果开始合并");
            return x + y;
        });
        System.out.println(result.join());
    }
}

 

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

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

相关文章

【华为OD机试真题 C++】TLV解析 【2022 Q4 | 100分】

■ 题目描述 TLV编码是按[Tag Length Value]格式进行编码的&#xff0c;一段码流中的信元用Tag标识&#xff0c;Tag在码流中唯一不重复&#xff0c;Length表示信元Value的长度&#xff0c;Value表示信元的值。 码流以某信元的Tag开头&#xff0c;Tag固定占一个字节&#xff0…

机器学习 | 逻辑回归

一.基本原理 面对一个分类问题&#xff0c;建立代价函数&#xff0c;通过优化方法迭代求解出最优的模型参数&#xff0c;然后测试验证我们这个求解的模型的好坏。逻辑回归是一种分类方法&#xff0c;主要用于二分类问题&#xff0c;应用于研究某些事件发生的概率 二.优缺点 …

day28【代码随想录】回溯之组合、组合总和|||、电话号码的字母组合

文章目录前言一、组合&#xff08;力扣77&#xff09;剪枝优化二、组合总和 III&#xff08;力扣216&#xff09;剪枝优化三、电话号码的字母组合&#xff08;力扣17&#xff09;总结前言 1、组合 2、组合总和||| 3、电话号码的字母组合 一、组合&#xff08;力扣77&#xff0…

第1章 计算机组成原理概述

文章目录前言1.0 课程简介1.0.1 课程的地位1.0.2 课程学习思路1.0.3 课程组成1.1 计算机系统简介1.1.1 计算机组成1.计算机的类型2.计算机的组成3.软件组成1.1.2 计算机系统的层次结构1.物理层方面2.程序员角度1.1.3 计算机体系结构与计算机组成1.2 计算机的基本组成1.2.1 冯诺…

esp8266测试1.44英寸TFT屏(驱动7735)的demo

参考这教程: 使用esp8266点亮福利屏型号st7735的1.44的TFT屏 管脚连接&#xff1a; 我的用的TFT1.44寸ST7735&#xff0c;与NodeMCU针脚接线成功连接 VCC——3V GND——G LED——3V CLK——D5 SDI——D7 RS——D6 RST——D4 CS——D8 这里给出常用的屏幕管脚定义 以及esp8266…

女生也能学编程:行政女生转行学编程获13000元薪资

“女生不能学编程” “女生学编程找不到工作” “企业根本不会招女生” …… 这样类似的说法&#xff0c;让非常多的女生放弃了学编程&#xff0c;但达妹今天要明确的说&#xff0c;这种说法是 错误的&#xff01; 只要你愿意改变&#xff0c;有梦想&#xff0c;想追求更好的…

想要快速准备好性能数据?方法这不就来了!

[内部资源] 想拿年薪30W的软件测试人员&#xff0c;这份资料必须领取~ Python自动化测试全栈性能测试全栈&#xff0c;挑战年薪40W 性能测试的一般流程 收集性能需求——>编写性能脚本——>执行性能测试——>分析测试报告——>系统性能调优。 在收集性能需求后…

Spring IOC\AOP\事务\注解

DAY1 一、引言 1.1 原生web开发中存在哪些问题&#xff1f; 传统Web开发存在硬编码所造成的过度程序耦合&#xff08;例如&#xff1a;Service中作为属性Dao对象&#xff09;。 部分Java EE API较为复杂&#xff0c;使用效率低&#xff08;例如&#xff1a;JDBC开发步骤&…

17. 【gRPC系列学习】http2 各类型帧的含义

本节介绍http2有哪些类型的帧以及各帧的主要作用,是rfc7540规范标准定义,文末有参考链接,为后续介绍gRPC帧处理做技术储备。 1. 帧结构 帧长度3个字节 24 bit帧类型1个字节,含义如下:FrameData FrameType = 0x0FrameHeaders FrameType = 0x1FramePriority …

MySQL#4(JDBC常用API详解)

目录 一.简介 1.概念 2.本质 3.优点 4.步骤 二.API详解 1.DriverManager(驱动管理类) 2.Connection 3.Statement 4.ResultSet 5.PreparedStatement 一.简介 1.概念 JDBC就是使用Java语言操作关系型数据库的一套API(Java DataBase Connectivity)Java 数据库连接 2.本…

年货节微信活动有哪些_分享微信小程序商城开发好处

新年临近&#xff0c;又是百姓们囤年货的日子。各行业的微商商城或者线下实体店的商家们&#xff0c;趁此机会别&#xff0c;做一波优惠促销活动&#xff0c;今年的业绩就靠它来个完美的收尾啦&#xff01; 1.类型&#xff1a;转盘拆福袋等抽奖活动 点击对应抽奖按钮&#xff0…

Doo Prime 提供高达 1000 倍杠杆,助您撬动无限机遇

2022 年 11 月 19 日&#xff0c;Doo Prime 正式将全部账户类型的可选杠杆从 1:500 上调至 1:1000 倍&#xff0c;提供更灵活的杠杆选择&#xff0c;让全球客户有机会以更少的资金撬动更高的潜在利润&#xff0c;进一步拓展投资机遇。 *备注&#xff1a;杠杆调整详情请参阅下文…

Sentinel系列——概述与安装1-1

Sentinel系列——概述与安装1-1概述服务雪崩解决方法基本概念资源规则Sentinel 是如何工作的安装Sentinel下载地址启动修改sentinel启动参数设置启动端口设置用户名密码概述 随着微服务的流行&#xff0c;服务和服务之间的稳定性变得越来越重要。Sentinel 是面向分布式、多语言…

面试官问 Redis 的数据结构的时候怎么答能加分?

一提到 Redis&#xff0c;我们的脑子里马上就会出现一个词&#xff1a;“快。”但是你有没有想过&#xff0c;Redis 的快&#xff0c;到底是快在哪里呢&#xff1f;实际上&#xff0c;这里有一个重要的表现&#xff1a;它接收到一个键值对操作后&#xff0c;能以微秒级别的速度…

【代码随想录】鱼与钰遇雨数据结构与算法刷题笔记

代码随想录 https://www.programmercarl.com/ 编程素养 代码风格 C代码风格参考google C style Guide 我使用的是驼峰命名法&#xff0c;其中空格留白的规则如下例&#xff1a; class Solution { public:void moveZeroes(vector<int>& nums) {int slowIndex 0…

化妆品商城小程序制作步骤_分享化妆品商城小程序开发好处

第一&#xff0c;用套餐做团购活动&#xff0c;主打节日套餐 随着疫情的反反复复&#xff0c;越来越多的用户都减少出门&#xff0c;那么就会减少到线下门店选购商品的机会&#xff0c;那么有一款化妆品商城小程序就可以直接在手机上下单&#xff0c;非常方便&#xff0c;那么我…

清华百度升级AIR白皮书2.0:发布车路协同重大突破

12月23日&#xff0c;全球首份车路协同自动驾驶技术创新白皮书《面向自动驾驶的车路协同关键技术与展望》升级发布2.0版(以下称“白皮书2.0”)&#xff0c;并向全行业公开征集意见。 该白皮书是全球车路协同技术研究领域最权威的报告之一&#xff0c;由张亚勤院士牵头&#xff…

DELMIA软件:机器人工作站中旋转台外围设备的运动仿真操作方法

目录 任务介绍 旋转台设备运动机构分析 旋转台设备模型导入与装配 旋转台设备示教编程 设备工艺添加与工艺序列设计 仿真运行 任务介绍 在DELMIA软件中制作旋转台设备运动机构&#xff0c;并实现机器人与旋转台设备联合运动虚拟仿真。仿真过程中&#xff0c;旋转台设备自…

机器学习肝炎预测模型machine learning for hepatitis prediction model

作者Toby&#xff0c;来自机器学习肝炎预测模型 肝炎是由细菌、病毒、寄生虫、酒精、药物、化学物质、自身免疫等多种致病因素引起的肝脏炎症的统称。儿童及成年人均可患病&#xff0c;病毒感染导致的病毒性肝炎较为常见。 由于过度饮酒、吸入有害气体、摄入受污染的食物、泡菜…

代码随想录刷题记录 day51 下一个更大元素II + 接雨水

代码随想录刷题记录 day51 下一个更大元素II 接雨水 503. 下一个更大元素 II 思想 和每日温度的思路是一样的&#xff0c;单调栈中存放的是元素的下标&#xff0c;需要学习的是如何模拟遍历两次数组。 for(int i1;i<nums.length*2;i){ ​ //这其中所有有关于i的 都用i …