我的编程空间,编程开发者的网络收藏夹
学习永远不晚

Java8 CompletableFuture异步多线程怎么实现

短信预约 -IT技能 免费直播动态提醒
省份

北京

  • 北京
  • 上海
  • 天津
  • 重庆
  • 河北
  • 山东
  • 辽宁
  • 黑龙江
  • 吉林
  • 甘肃
  • 青海
  • 河南
  • 江苏
  • 湖北
  • 湖南
  • 江西
  • 浙江
  • 广东
  • 云南
  • 福建
  • 海南
  • 山西
  • 四川
  • 陕西
  • 贵州
  • 安徽
  • 广西
  • 内蒙
  • 西藏
  • 新疆
  • 宁夏
  • 兵团
手机号立即预约

请填写图片验证码后获取短信验证码

看不清楚,换张图片

免费获取短信验证码

Java8 CompletableFuture异步多线程怎么实现

这篇文章主要介绍了Java8 CompletableFuture异步多线程怎么实现的相关知识,内容详细易懂,操作简单快捷,具有一定借鉴价值,相信大家阅读完这篇Java8 CompletableFuture异步多线程怎么实现文章都会有所收获,下面我们一起来看看吧。

1、一个示例回顾Future

一些业务场景我们需要使用多线程异步执行任务,加快任务执行速度。

JDK5新增了Future接口,用于描述一个异步计算的结果。

虽然 Future 以及相关使用方法提供了异步执行任务的能力,但是对于结果的获取却是很不方便,我们必须使用Future.get()的方式阻塞调用线程,或者使用轮询方式判断 Future.isDone 任务是否结束,再获取结果。

这两种处理方式都不是很优雅,相关代码如下:

    @Test    public void testFuture() throws ExecutionException, InterruptedException {        ExecutorService executorService = Executors.newFixedThreadPool(5);        Future<String> future = executorService.submit(() -> {            Thread.sleep(2000);            return "hello";        });        System.out.println(future.get());        System.out.println("end");    }

与此同时,Future无法解决多个异步任务需要相互依赖的场景,简单点说就是,主线程需要等待子线程任务执行完毕之后在进行执行,这个时候你可能想到了「CountDownLatch」,没错确实可以解决,代码如下。

这里定义两个Future,第一个通过用户id获取用户信息,第二个通过商品id获取商品信息。

    @Test    public void testCountDownLatch() throws InterruptedException, ExecutionException {        ExecutorService executorService = Executors.newFixedThreadPool(5);        CountDownLatch downLatch = new CountDownLatch(2);        long startTime = System.currentTimeMillis();        Future<String> userFuture = executorService.submit(() -> {            //模拟查询商品耗时500毫秒            Thread.sleep(500);            downLatch.countDown();            return "用户A";        });         Future<String> goodsFuture = executorService.submit(() -> {            //模拟查询商品耗时500毫秒            Thread.sleep(400);            downLatch.countDown();            return "商品A";        });         downLatch.await();        //模拟主程序耗时时间        Thread.sleep(600);        System.out.println("获取用户信息:" + userFuture.get());        System.out.println("获取商品信息:" + goodsFuture.get());        System.out.println("总共用时" + (System.currentTimeMillis() - startTime) + "ms");     }

「运行结果」

获取用户信息:用户A
获取商品信息:商品A
总共用时1110ms

从运行结果可以看出结果都已经获取,而且如果我们不用异步操作,执行时间应该是:500+400+600 = 1500,用异步操作后实际只用1110。

但是Java8以后我不在认为这是一种优雅的解决方式,接下来来了解下CompletableFuture的使用。

2、通过CompletableFuture实现上面示例

    @Test    public void testCompletableInfo() throws InterruptedException, ExecutionException {        long startTime = System.currentTimeMillis();         //调用用户服务获取用户基本信息        CompletableFuture<String> userFuture = CompletableFuture.supplyAsync(() ->                //模拟查询商品耗时500毫秒        {            try {                Thread.sleep(500);            } catch (InterruptedException e) {                e.printStackTrace();            }            return "用户A";        });         //调用商品服务获取商品基本信息        CompletableFuture<String> goodsFuture = CompletableFuture.supplyAsync(() ->                //模拟查询商品耗时500毫秒        {            try {                Thread.sleep(400);            } catch (InterruptedException e) {                e.printStackTrace();            }            return "商品A";        });         System.out.println("获取用户信息:" + userFuture.get());        System.out.println("获取商品信息:" + goodsFuture.get());         //模拟主程序耗时时间        Thread.sleep(600);        System.out.println("总共用时" + (System.currentTimeMillis() - startTime) + "ms");    }

运行结果

获取用户信息:用户A
获取商品信息:商品A
总共用时1112ms

通过CompletableFuture可以很轻松的实现CountDownLatch的功能,你以为这就结束了,远远不止,CompletableFuture比这要强多了。

比如可以实现:任务1执行完了再执行任务2,甚至任务1执行的结果,作为任务2的入参数等等强大功能,下面就来学学CompletableFuture的API。

3、CompletableFuture创建方式

3.1、常用的4种创建方式

CompletableFuture源码中有四个静态方法用来执行异步任务

public static <U> CompletableFuture<U> supplyAsync(Supplier<U> supplier){..}public static <U> CompletableFuture<U> supplyAsync(Supplier<U> supplier,Executor executor){..}public static CompletableFuture<Void> runAsync(Runnable runnable){..}public static CompletableFuture<Void> runAsync(Runnable runnable,Executor executor){..}

一般我们用上面的静态方法来创建CompletableFuture,这里也解释下他们的区别:

  • 「supplyAsync」执行任务,支持返回值。

  • 「runAsync」执行任务,没有返回值。

1.1、「supplyAsync方法」

//使用默认内置线程池ForkJoinPool.commonPool(),根据supplier构建执行任务public static <U> CompletableFuture<U> supplyAsync(Supplier<U> supplier)//自定义线程,根据supplier构建执行任务public static <U> CompletableFuture<U> supplyAsync(Supplier<U> supplier, Executor executor)

1.2、「runAsync方法」

//使用默认内置线程池ForkJoinPool.commonPool(),根据runnable构建执行任务public static CompletableFuture<Void> runAsync(Runnable runnable) //自定义线程,根据runnable构建执行任务public static CompletableFuture<Void> runAsync(Runnable runnable,  Executor executor)

3.2、结果获取的4种方式

对于结果的获取CompltableFuture类提供了四种方式

//方式一public T get()//方式二public T get(long timeout, TimeUnit unit)//方式三public T getNow(T valueIfAbsent)//方式四public T join()

说明:

  • 「get()和get(long timeout, TimeUnit unit)」 => 在Future中就已经提供了,后者提供超时处理,如果在指定时间内未获取结果将抛出超时异常

  • 「getNow」 => 立即获取结果不阻塞,结果计算已完成将返回结果或计算过程中的异常,如果未计算完成将返回设定的valueIfAbsent值

  • 「join」 => 方法里不会抛出异常

示例

    @Test    public void testCompletableGet() throws InterruptedException, ExecutionException {         CompletableFuture<String> cp1 = CompletableFuture.supplyAsync(() -> {            try {                Thread.sleep(1000);            } catch (InterruptedException e) {                e.printStackTrace();            }            return "商品A";        });         // getNow方法测试         System.out.println(cp1.getNow("商品B"));         //join方法测试         CompletableFuture<Integer> cp2 = CompletableFuture.supplyAsync((() -> 1 / 0));        System.out.println(cp2.join());        System.out.println("-----------------------------------------------------");        //get方法测试        CompletableFuture<Integer> cp3 = CompletableFuture.supplyAsync((() -> 1 / 0));        System.out.println(cp3.get());    }

「运行结果」:

  • 第一个执行结果为 「商品B」,因为要先睡上1秒结果不能立即获取

  • join方法获取结果方法里不会抛异常,但是执行结果会抛异常,抛出的异常为CompletionException

  • get方法获取结果方法里将抛出异常,执行结果抛出的异常为ExecutionException

4、异步回调方法

Java8 CompletableFuture异步多线程怎么实现

4.1、thenRun/thenRunAsync

通俗点讲就是,「做完第一个任务后,再做第二个任务,第二个任务也没有返回值」

示例

    @Test    public void testCompletableThenRunAsync() throws InterruptedException, ExecutionException {        long startTime = System.currentTimeMillis();         CompletableFuture<Void> cp1 = CompletableFuture.runAsync(() -> {            try {                //执行任务A                Thread.sleep(600);            } catch (InterruptedException e) {                e.printStackTrace();            }         });         CompletableFuture<Void> cp2 = cp1.thenRun(() -> {            try {                //执行任务B                Thread.sleep(400);            } catch (InterruptedException e) {                e.printStackTrace();            }        });         // get方法测试        System.out.println(cp2.get());         //模拟主程序耗时时间        Thread.sleep(600);        System.out.println("总共用时" + (System.currentTimeMillis() - startTime) + "ms");    }     //运行结果    

「thenRun 和thenRunAsync有什么区别呢?」

如果你执行第一个任务的时候,传入了一个自定义线程池:

  • 调用thenRun方法执行第二个任务时,则第二个任务和第一个任务是共用同一个线程池。

  • 调用thenRunAsync执行第二个任务时,则第一个任务使用的是你自己传入的线程池,第二个任务使用的是ForkJoin线程池。

说明: 后面介绍的thenAccept和thenAcceptAsync,thenApply和thenApplyAsync等,它们之间的区别也是这个。

4.2、thenAccept/thenAcceptAsync

第一个任务执行完成后,执行第二个回调方法任务,会将该任务的执行结果,作为入参,传递到回调方法中,但是回调方法是没有返回值的。

示例

    @Test    public void testCompletableThenAccept() throws ExecutionException, InterruptedException {        long startTime = System.currentTimeMillis();        CompletableFuture<String> cp1 = CompletableFuture.supplyAsync(() -> {            return "dev";         });        CompletableFuture<Void> cp2 = cp1.thenAccept((a) -> {            System.out.println("上一个任务的返回结果为: " + a);        });         cp2.get();    }

4.3、 thenApply/thenApplyAsync

表示第一个任务执行完成后,执行第二个回调方法任务,会将该任务的执行结果,作为入参,传递到回调方法中,并且回调方法是有返回值的。

示例

    @Test    public void testCompletableThenApply() throws ExecutionException, InterruptedException {        CompletableFuture<String> cp1 = CompletableFuture.supplyAsync(() -> {            return "dev";         }).thenApply((a) -> {            if (Objects.equals(a, "dev")) {                return "dev";            }            return "prod";        });         System.out.println("当前环境为:" + cp1.get());         //输出: 当前环境为:dev    }

5、异常回调

当CompletableFuture的任务不论是正常完成还是出现异常它都会调用「whenComplete」这回调函数。

  • 「正常完成」:whenComplete返回结果和上级任务一致,异常为null;

  • 「出现异常」:whenComplete返回结果为null,异常为上级任务的异常;

即调用get()时,正常完成时就获取到结果,出现异常时就会抛出异常,需要你处理该异常。

下面来看看示例

5.1、只用whenComplete

    @Test    public void testCompletableWhenComplete() throws ExecutionException, InterruptedException {        CompletableFuture<Double> future = CompletableFuture.supplyAsync(() -> {             if (Math.random() < 0.5) {                throw new RuntimeException("出错了");            }            System.out.println("正常结束");            return 0.11;         }).whenComplete((aDouble, throwable) -> {            if (aDouble == null) {                System.out.println("whenComplete aDouble is null");            } else {                System.out.println("whenComplete aDouble is " + aDouble);            }            if (throwable == null) {                System.out.println("whenComplete throwable is null");            } else {                System.out.println("whenComplete throwable is " + throwable.getMessage());            }        });        System.out.println("最终返回的结果 = " + future.get());    }

正常完成,没有异常时:

正常结束
whenComplete aDouble is 0.11
whenComplete throwable is null
最终返回的结果 = 0.11

出现异常时:get()会抛出异常

whenComplete aDouble is null
whenComplete throwable is java.lang.RuntimeException: 出错了
 
java.util.concurrent.ExecutionException: java.lang.RuntimeException: 出错了
 at java.util.concurrent.CompletableFuture.reportGet(CompletableFuture.java:357)
 at java.util.concurrent.CompletableFuture.get(CompletableFuture.java:1895)

5.2、whenComplete + exceptionally示例

    @Test    public void testWhenCompleteExceptionally() throws ExecutionException, InterruptedException {        CompletableFuture<Double> future = CompletableFuture.supplyAsync(() -> {            if (Math.random() < 0.5) {                throw new RuntimeException("出错了");            }            System.out.println("正常结束");            return 0.11;         }).whenComplete((aDouble, throwable) -> {            if (aDouble == null) {                System.out.println("whenComplete aDouble is null");            } else {                System.out.println("whenComplete aDouble is " + aDouble);            }            if (throwable == null) {                System.out.println("whenComplete throwable is null");            } else {                System.out.println("whenComplete throwable is " + throwable.getMessage());            }        }).exceptionally((throwable) -> {            System.out.println("exceptionally中异常:" + throwable.getMessage());            return 0.0;        });         System.out.println("最终返回的结果 = " + future.get());    }

当出现异常时,exceptionally中会捕获该异常,给出默认返回值0.0。

whenComplete aDouble is null
whenComplete throwable is java.lang.RuntimeException: 出错了
exceptionally中异常:java.lang.RuntimeException: 出错了
最终返回的结果 = 0.0

6、多任务组合回调

Java8 CompletableFuture异步多线程怎么实现

6.1、AND组合关系

thenCombine / thenAcceptBoth / runAfterBoth都表示:「当任务一和任务二都完成再执行任务三」

区别在于:

  • 「runAfterBoth」 不会把执行结果当做方法入参,且没有返回值

  • 「thenAcceptBoth」: 会将两个任务的执行结果作为方法入参,传递到指定方法中,且无返回值

  • 「thenCombine」:会将两个任务的执行结果作为方法入参,传递到指定方法中,且有返回值

示例

    @Test    public void testCompletableThenCombine() throws ExecutionException, InterruptedException {        //创建线程池        ExecutorService executorService = Executors.newFixedThreadPool(10);        //开启异步任务1        CompletableFuture<Integer> task = CompletableFuture.supplyAsync(() -> {            System.out.println("异步任务1,当前线程是:" + Thread.currentThread().getId());            int result = 1 + 1;            System.out.println("异步任务1结束");            return result;        }, executorService);         //开启异步任务2        CompletableFuture<Integer> task2 = CompletableFuture.supplyAsync(() -> {            System.out.println("异步任务2,当前线程是:" + Thread.currentThread().getId());            int result = 1 + 1;            System.out.println("异步任务2结束");            return result;        }, executorService);         //任务组合        CompletableFuture<Integer> task3 = task.thenCombineAsync(task2, (f1, f2) -> {            System.out.println("执行任务3,当前线程是:" + Thread.currentThread().getId());            System.out.println("任务1返回值:" + f1);            System.out.println("任务2返回值:" + f2);            return f1 + f2;        }, executorService);         Integer res = task3.get();        System.out.println("最终结果:" + res);    }

「运行结果」

异步任务1,当前线程是:17
异步任务1结束
异步任务2,当前线程是:18
异步任务2结束
执行任务3,当前线程是:19
任务1返回值:2
任务2返回值:2
最终结果:4

6.2、OR组合关系

applyToEither / acceptEither / runAfterEither 都表示:「两个任务,只要有一个任务完成,就执行任务三」

区别在于:

  • 「runAfterEither」:不会把执行结果当做方法入参,且没有返回值

  • 「acceptEither」: 会将已经执行完成的任务,作为方法入参,传递到指定方法中,且无返回值

  • 「applyToEither」:会将已经执行完成的任务,作为方法入参,传递到指定方法中,且有返回值

示例

    @Test    public void testCompletableEitherAsync() {        //创建线程池        ExecutorService executorService = Executors.newFixedThreadPool(10);        //开启异步任务1        CompletableFuture<Integer> task = CompletableFuture.supplyAsync(() -> {            System.out.println("异步任务1,当前线程是:" + Thread.currentThread().getId());             int result = 1 + 1;            System.out.println("异步任务1结束");            return result;        }, executorService);         //开启异步任务2        CompletableFuture<Integer> task2 = CompletableFuture.supplyAsync(() -> {            System.out.println("异步任务2,当前线程是:" + Thread.currentThread().getId());            int result = 1 + 2;            try {                Thread.sleep(3000);            } catch (InterruptedException e) {                e.printStackTrace();            }            System.out.println("异步任务2结束");            return result;        }, executorService);         //任务组合        task.acceptEitherAsync(task2, (res) -> {            System.out.println("执行任务3,当前线程是:" + Thread.currentThread().getId());            System.out.println("上一个任务的结果为:" + res);        }, executorService);    }

运行结果

//通过结果可以看出,异步任务2都没有执行结束,任务3获取的也是1的执行结果
异步任务1,当前线程是:17
异步任务1结束
异步任务2,当前线程是:18
执行任务3,当前线程是:19
上一个任务的结果为:2

注意

如果把上面的核心线程数改为1也就是

 ExecutorService executorService = Executors.newFixedThreadPool(1);

运行结果就是下面的了,会发现根本没有执行任务3,显然是任务3直接被丢弃了。

异步任务1,当前线程是:17
异步任务1结束
异步任务2,当前线程是:17

6.3、多任务组合

  • 「allOf」:等待所有任务完成

  • 「anyOf」:只要有一个任务完成

示例

allOf:等待所有任务完成

    @Test    public void testCompletableAallOf() throws ExecutionException, InterruptedException {        //创建线程池        ExecutorService executorService = Executors.newFixedThreadPool(10);        //开启异步任务1        CompletableFuture<Integer> task = CompletableFuture.supplyAsync(() -> {            System.out.println("异步任务1,当前线程是:" + Thread.currentThread().getId());            int result = 1 + 1;            System.out.println("异步任务1结束");            return result;        }, executorService);         //开启异步任务2        CompletableFuture<Integer> task2 = CompletableFuture.supplyAsync(() -> {            System.out.println("异步任务2,当前线程是:" + Thread.currentThread().getId());            int result = 1 + 2;            try {                Thread.sleep(3000);            } catch (InterruptedException e) {                e.printStackTrace();            }            System.out.println("异步任务2结束");            return result;        }, executorService);         //开启异步任务3        CompletableFuture<Integer> task3 = CompletableFuture.supplyAsync(() -> {            System.out.println("异步任务3,当前线程是:" + Thread.currentThread().getId());            int result = 1 + 3;            try {                Thread.sleep(4000);            } catch (InterruptedException e) {                e.printStackTrace();            }            System.out.println("异步任务3结束");            return result;        }, executorService);         //任务组合        CompletableFuture<Void> allOf = CompletableFuture.allOf(task, task2, task3);         //等待所有任务完成        allOf.get();        //获取任务的返回结果        System.out.println("task结果为:" + task.get());        System.out.println("task2结果为:" + task2.get());        System.out.println("task3结果为:" + task3.get());    }

anyOf: 只要有一个任务完成

    @Test    public void testCompletableAnyOf() throws ExecutionException, InterruptedException {        //创建线程池        ExecutorService executorService = Executors.newFixedThreadPool(10);        //开启异步任务1        CompletableFuture<Integer> task = CompletableFuture.supplyAsync(() -> {            int result = 1 + 1;            return result;        }, executorService);         //开启异步任务2        CompletableFuture<Integer> task2 = CompletableFuture.supplyAsync(() -> {            int result = 1 + 2;            return result;        }, executorService);         //开启异步任务3        CompletableFuture<Integer> task3 = CompletableFuture.supplyAsync(() -> {            int result = 1 + 3;            return result;        }, executorService);         //任务组合        CompletableFuture<Object> anyOf = CompletableFuture.anyOf(task, task2, task3);        //只要有一个有任务完成        Object o = anyOf.get();        System.out.println("完成的任务的结果:" + o);    }

7、CompletableFuture使用有哪些注意点

Java8 CompletableFuture异步多线程怎么实现

 CompletableFuture 使我们的异步编程更加便利的、代码更加优雅的同时,我们也要关注下它,使用的一些注意点。

7.1、Future需要获取返回值,才能获取异常信息

    @Test    public void testWhenCompleteExceptionally() {        CompletableFuture<Double> future = CompletableFuture.supplyAsync(() -> {            if (1 == 1) {                throw new RuntimeException("出错了");            }            return 0.11;        });         //如果不加 get()方法这一行,看不到异常信息        //future.get();    }

Future需要获取返回值,才能获取到异常信息。如果不加 get()/join()方法,看不到异常信息。

小伙伴们使用的时候,注意一下哈,考虑是否加try...catch...或者使用exceptionally方法。

7.2、CompletableFuture的get()方法是阻塞的

CompletableFuture的get()方法是阻塞的,如果使用它来获取异步调用的返回值,需要添加超时时间。

//反例 CompletableFuture.get();//正例CompletableFuture.get(5, TimeUnit.SECONDS);

7.3、不建议使用默认线程池

CompletableFuture代码中又使用了默认的「ForkJoin线程池」,处理的线程个数是电脑「CPU核数-1」。在大量请求过来的时候,处理逻辑复杂的话,响应会很慢。一般建议使用自定义线程池,优化线程池配置参数。

7.4、自定义线程池时,注意饱和策略

CompletableFuture的get()方法是阻塞的,我们一般建议使用future.get(5, TimeUnit.SECONDS)。并且一般建议使用自定义线程池。

但是如果线程池拒绝策略是DiscardPolicy或者DiscardOldestPolicy,当线程池饱和时,会直接丢弃任务,不会抛弃异常。因此建议,CompletableFuture线程池策略最好使用AbortPolicy,然后耗时的异步线程,做好线程池隔离哈。

关于“Java8 CompletableFuture异步多线程怎么实现”这篇文章的内容就介绍到这里,感谢各位的阅读!相信大家对“Java8 CompletableFuture异步多线程怎么实现”知识都有一定的了解,大家如果还想学习更多知识,欢迎关注编程网行业资讯频道。

免责声明:

① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。

② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341

Java8 CompletableFuture异步多线程怎么实现

下载Word文档到电脑,方便收藏和打印~

下载Word文档

猜你喜欢

Java8 CompletableFuture异步多线程怎么实现

这篇文章主要介绍了Java8 CompletableFuture异步多线程怎么实现的相关知识,内容详细易懂,操作简单快捷,具有一定借鉴价值,相信大家阅读完这篇Java8 CompletableFuture异步多线程怎么实现文章都会有所收获,
2023-07-05

Java8 CompletableFuture 异步多线程的实现

本文主要介绍了Java8 CompletableFuture 异步多线程的实现,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
2023-05-14

Java8通过CompletableFuture怎么实现异步回调

本篇内容介绍了“Java8通过CompletableFuture怎么实现异步回调”的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!希望大家仔细阅读,能够学有所成!1 什么是Co
2023-06-30

django多线程异步任务怎么实现

在Django中,可以使用Celery来实现多线程异步任务。首先,需要安装Celery:pip install celery然后,在Django项目的settings.py文件中配置Celery:python# settings.pyCEL
2023-10-21

java多线程通过CompletableFuture组装异步计算单元

这篇文章主要为大家介绍了java多线程通过CompletableFuture组装异步计算单元,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
2023-05-18

Python多线程、异步+多进程爬虫实现代码

安装Tornado 省事点可以直接用grequests库,下面用的是tornado的异步client。 异步用到了tornado,根据官方文档的例子修改得到一个简单的异步爬虫类。可以参考下最新的文档学习下。 pip install tor
2022-06-04

C语言单线程怎么实现异步

在C语言的单线程环境中,要实现异步,可以使用以下几种方式:1. 使用信号(Signal):可以使用 `signal` 函数来设置信号处理函数,当某个事件发生时,触发信号处理函数执行相应的操作。在信号处理函数中可以处理异步操作。2. 使用定时
2023-10-12

C#异步多线程ThreadPool怎么使用

这篇文章主要讲解了“C#异步多线程ThreadPool怎么使用”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习“C#异步多线程ThreadPool怎么使用”吧!启动线程池线程ThreadPool
2023-06-25

Java中怎么实现多线程同步

今天就跟大家聊聊有关Java中怎么实现多线程同步,可能很多人都不太了解,为了让大家更加了解,小编给大家总结了以下内容,希望大家根据这篇文章可以有所收获。让我们从JVM的角度来看看锁这个概念:在Java程序运行时环境中,JVM需要对两类线程共
2023-06-17

C#多线程控制进度条的异步调用怎么实现

这篇文章主要讲解了“C#多线程控制进度条的异步调用怎么实现”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习“C#多线程控制进度条的异步调用怎么实现”吧!看看具体的步骤和实现:在上面的代码中,我们
2023-06-17

django多线程异步任务的实现原理是什么

Django多线程异步任务的实现原理是基于Python的内置模块`threading`和Django的任务队列模块`django-q`来实现的。以下是其大致的实现原理:1. 定义任务:在Django中使用`@task`装饰器来定义异步任务。
2023-09-26

C#异步委托和多线程怎么理解

这篇文章主要讲解了“C#异步委托和多线程怎么理解”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习“C#异步委托和多线程怎么理解”吧!关于这个问题,我想很多初学者跟我一样有很多疑问吧。下面我说的内
2023-06-18

Java中怎样实现多线程同步

本篇文章给大家分享的是有关Java中怎样实现多线程同步,小编觉得挺实用的,因此分享给大家学习,希望大家阅读完这篇文章后可以有所收获,话不多说,跟着小编一起来看看吧。不同步时的代码Bank.java package threadTest;
2023-06-17

Java如何实现多线程、线程同步

这篇文章主要介绍了Java如何实现多线程、线程同步的相关知识,内容详细易懂,操作简单快捷,具有一定借鉴价值,相信大家阅读完这篇Java如何实现多线程、线程同步文章都会有所收获,下面我们一起来看看吧。1 多线程1.1 进程进程:是正在运行的程
2023-06-30

Java多线程开发工具之CompletableFuture怎么应用

这篇“Java多线程开发工具之CompletableFuture怎么应用”文章的知识点大部分人都不太理解,所以小编给大家总结了以下内容,内容详细,步骤清晰,具有一定的借鉴价值,希望大家阅读完这篇文章能有所收获,下面我们一起来看看这篇“Jav
2023-07-05

编程热搜

  • Python 学习之路 - Python
    一、安装Python34Windows在Python官网(https://www.python.org/downloads/)下载安装包并安装。Python的默认安装路径是:C:\Python34配置环境变量:【右键计算机】--》【属性】-
    Python 学习之路 - Python
  • chatgpt的中文全称是什么
    chatgpt的中文全称是生成型预训练变换模型。ChatGPT是什么ChatGPT是美国人工智能研究实验室OpenAI开发的一种全新聊天机器人模型,它能够通过学习和理解人类的语言来进行对话,还能根据聊天的上下文进行互动,并协助人类完成一系列
    chatgpt的中文全称是什么
  • C/C++中extern函数使用详解
  • C/C++可变参数的使用
    可变参数的使用方法远远不止以下几种,不过在C,C++中使用可变参数时要小心,在使用printf()等函数时传入的参数个数一定不能比前面的格式化字符串中的’%’符号个数少,否则会产生访问越界,运气不好的话还会导致程序崩溃
    C/C++可变参数的使用
  • css样式文件该放在哪里
  • php中数组下标必须是连续的吗
  • Python 3 教程
    Python 3 教程 Python 的 3.0 版本,常被称为 Python 3000,或简称 Py3k。相对于 Python 的早期版本,这是一个较大的升级。为了不带入过多的累赘,Python 3.0 在设计的时候没有考虑向下兼容。 Python
    Python 3 教程
  • Python pip包管理
    一、前言    在Python中, 安装第三方模块是通过 setuptools 这个工具完成的。 Python有两个封装了 setuptools的包管理工具: easy_install  和  pip , 目前官方推荐使用 pip。    
    Python pip包管理
  • ubuntu如何重新编译内核
  • 改善Java代码之慎用java动态编译

目录