线程几种实现方式、异步编排笔记

一.初始化线程的4种方式

1.继承Thread

 //继承Thread
    public static void main(String[] args) {
        System.out.println("----------主线程开始---------");
        //继承Thread
        Thread01 thread01 = new Thread01();
        thread01.start();
        System.out.println("-------主线程结束------");
    }


    public static class Thread01 extends Thread{
        @Override
        public void run() {
            System.out.println("当前线程"+Thread.currentThread().getId());
            int i = 10/2;
            System.out.println("当前线程运行结果"+i);
        }
    }

2.实现Runable:

这种方式更为灵活,因为java是单继承,如果你的类已经继承了其他类,你仍然可以实现Runable来实现多线程。

   public static void main(String[] args) {
        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("当前线程:"+Thread.currentThread().getId());
            int i = 10/2;
            System.out.println("当前运行结果:" + i);
        }
    }

3.实现Callable接口+FutureTask:

Callable接口允许线程返回结果,并且可以抛出异常,结合FutureTask可以异步获取线程执行结果。

 public static void main(String[] args) throws ExecutionException, InterruptedException {
        System.out.println("----------主线程开始---------");

        Callable01 callable01 = new Callable01();
        FutureTask<Integer> task = new FutureTask<>(callable01);
        Thread thread = new Thread(task);
        thread.start();
        //阻塞等待整个线程执行完,获取返回结果
        Integer integer = task.get();
        System.out.println("------获取的返回结果-------"+integer);
        System.out.println("-------主线程结束------");
    }

    public static class Callable01 implements Callable<Integer> {

        @Override
        public Integer call() throws Exception {
            System.out.println("当前线程:"+Thread.currentThread().getId());
            int i = 10/2;
            System.out.println("当前运行结果:" + i);
            return i;

        }
    }

4.线程池:

使用线程池可以管理和复用线程,避免频繁创建和销毁线程,提高了资源利用率。

     //初始化线程池
    //Executors.newFixedThreadPool(3);
    public static ThreadPoolExecutor executor = new ThreadPoolExecutor(
            5,
            100,
            10,
            TimeUnit.SECONDS,
            new LinkedBlockingDeque<>(10000),
            Executors.defaultThreadFactory(),
            new ThreadPoolExecutor.AbortPolicy()
    );

    public static void main(String[] args) throws ExecutionException, InterruptedException {
        System.out.println("----------主线程开始---------");

        executor.execute(new Runnable01());
        System.out.println("-------主线程结束------");
    }

    public static class Runnable01 implements Runnable {
        @Override
        public void run() {
            System.out.println("当前线程:" + Thread.currentThread().getId());
            int i = 10 / 2;
            System.out.println("当前运行结果:" + i);
        }
    }

通过线程池性能稳定,也可以获取执行结果,并捕获异常,但是在业务复杂的情况下,一个异步调用可能会依赖于另一个异步调用的执行结果。

二.线程池

1.线程池的七大参数

(1)corePoolSize[5]:核心线程池【一直存在,除非allowCoreThreadTimeOut】,创建好以后就准备就绪的线程数量,等待接收异步任务去执行5个 Thread thread = new Thread(),thread.start。

(2)maximumPoolSize[200]:最大线程数,控制资源。

(3)keepAliveTime:存活时间。

(4)unit:时间单位。

(5)BlockingQueue<Runnable> workQueue:阻塞队列,如果任务有很多,就会将多的任务放在队列里,只要线程空闲,就会去队列里取出新的任务继续执行。

(6)ThreadFactory:创建线程的工厂。

(7)RejectedExecutionHandler handler:如果队列满了,按照我们指定的策略,拒绝执行。

2.运行流程

  1. 线程池创建,准备好core数量的核心线程,准备接受任务。

  2. 新的任务进来,用core准备好的空闲线程执行。

     (1)core满了,就将再次进来的任务放到阻塞队列中,空闲的core会自己去阻塞队列获取任务执行。

    (2)阻塞队列满了,就直接开启新线程执行,最大只能开到max指定的数量。

    (3)max都执行好了,max-core数量空闲的线程会在keepAliveTime 指定的时间后自动销毁,最终保持到core大小。

    (4)如果线程开到max的数量,还有新任务进来,就会使用reject指定的拒绝策略来进行处理。 

  3. 所有线程的创建都是由指定的Factory创建的。

 面试题:一个线程池core=8,max=20,queue=50,100并发进来怎么分配的

 首先会有8个线程进行执行,接下来50个线程会到线程队列中排队,因为最大线程为20,所以它会在开20-8=12个线程去执行,现在有70个线程已经安排上了,那么剩下的30个线程会执行默认的拒绝策略。

三.CompletableFuture组合式异步编程

(小伙伴不要去死记这些方法,具体应用我们要根据自己的业务来查找对应的编排方法,写法大差不差一样,所以我们知道怎么用即可,没必要浪费时间去记各个用法)

CompletableFuture是Java 8中引入的一个功能强大的异步编程工具类,它基于Future和CompletionStage接口构建,主要用于异步执行任务并返回结果,实现异步计算和操作组合。

  • 异步执行:他可以在新的线程上执行计算或者操作,而不会阻塞主线程,提高线程的响应速度

  • 可组合性:其操作可以组合成多个CompletableFuture构成复杂的异步计算链,使我们更容易的构成复杂的异步操作流水线

  • 异常处理:通过exceptionally()方法来捕获异常并返回默认值

  • 取消与超时:可以取消异步任务,还可以设置超时时间来避免任务的无限期等待

  • 非阻塞式等待:提供了非阻塞式等待方法,如join()和getNow()方法

1.创建异步对象

(1)runAsync和supplyAsync

CompletableFuture提供了四种静态方法来创建一个异步操作

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

没有指定Executor的方法会使用ForkJoinPool.commonPool()作为它的线程池执行异步代码,如果指定线程池,则使用指定的线程池运行,以下所有的方法都类同

  • runXxxx都是没有返回结果的,supplyXxxx都是可以获取返回结果的

  • 可以传入自动义的线程池,否则就用默认的线程池

代码如下:

 //初始化一个线程池
    public static ThreadPoolExecutor executor = new ThreadPoolExecutor(
            5,
            200,
            10,
            TimeUnit.SECONDS,
            new LinkedBlockingQueue<>(100000),
            Executors.defaultThreadFactory(),
            new ThreadPoolExecutor.AbortPolicy());

    public static void main(String[] args) throws ExecutionException, InterruptedException {
        System.out.println("---------主线程开始--------");
        //runAsnyc
        CompletableFuture<Void> runAsync = CompletableFuture.runAsync(() -> {
            System.out.println("------runAsync当前线程--------");
            int i = 10 / 2;
            System.out.println("runAsync当前运行结果:" + i);
        }, executor);

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

2.计算结果完成时的回调方法

当CompletableFuture的计算结果完成,或者抛出异常的时候,可以执行特定的Action,主要是下边的方法:

public CompletableFuture<T> whenComplete(BiConsumer<? super T,? super Throwable> action)
public CompletableFuture<T> whenCompleteAsync(BiConsumer<? super T,? super Throwable> action)
public CompletableFuture<T> whenCompleteAsync(BiConsumer<? super T,? super Throwable> action, Executor executor)
public CompletableFuture<T> exceptionally(Function<Throwable,? extends T> fn)

whenComplete可以处理正常和异常的计算结果,exceptionally 处理异常情况。

whenComplete 和 whenCompleteAsync 的区别:

  • whenComplete:它的回调函数会在执行当前任务的线程上进行执行,也就是说,如果当前CompletableFuture是在某个特定的线程上完成的,,那么whenComplete的回调函数也会在该线程上执行。

  • whenCompleteAsync 他的回调函数会被提交给线程池(如果提供了),或者默认 ForkJoinPool.commonPool 线程池来执行,也就是说,即使compleableFuture是在某个特定的线程上完成,whenCompleteAsync的回调函数也是在另一个线程上执行。

代码如下:

 public static void main(String[] args) throws ExecutionException, InterruptedException {
        CompletableFuture<Integer> supplyAsync = CompletableFuture.supplyAsync(() -> {
            System.out.println("supplyAsync当前线程:" + Thread.currentThread().getId());
            int i = 10 / 2;
            System.out.println("supplyAsync当前运行结果:" + i);
            return i;
        }, executor).whenComplete((result,exception)->{
            System.out.println("异步任务完成了----结果是"+result+"异常是"+exception);
        }).exceptionally(throwable -> 10);
        Integer integer = supplyAsync.get();
        System.out.println("supplyAsync获取当前运行结果:" + integer);
        System.out.println("----------主线程结束----------");
    }

handle 方法

handle是完成任务时对结果的处理,handle方法和thenApply方法处理的方式基本一样,不同的是handle是在任务完成之后去执行的,还可以处理异常任务,而thenApply只能处理执行正常的任务,任务执行异常则不执行thenApply。

public <U> CompletionStage<U> handle(BiFunction<? super T, Throwable, ? extends U> fn);
public <U> CompletionStage<U> handleAsync(BiFunction<? super T, Throwable, ? extends U> fn);
public <U> CompletionStage<U> handleAsync(BiFunction<? super T, Throwable, ? extends U> fn,Execut

和complete一样,可对结果进行处理,可改变返回值

  public static void main(String[] args) throws ExecutionException, InterruptedException {
        CompletableFuture<Integer> handleFuture = CompletableFuture.supplyAsync(() -> {
            System.out.println("handleFuture当前线程:" + Thread.currentThread().getId());
            int i = 10 / 2;
            System.out.println("handleFuture当前运行结果:" + i);
            return i;
        }, executor).handle((result,excetion)->{
            if (result!=null){
                return result*2;
            }
            if (excetion!=null){
                return 0;
            }
            return 0;
        });
        Integer integer = handleFuture.get();
        System.out.println("最终的结果是:"+integer);
    }

线程串行化
public <U > completableFuture < U > thenApply(Function < ? super T, ? extends U > fn);
public <U > completableFuture < U > thenApplyAsync(Function < ? super T, ? extends U > fn);
public <U > CompletableFuture < U > thenApplyAsync(Function < ? super T, ? extends U > fn, Executor executor);
 
public completionStage<Void> thenAccept (consumer < ? super T > action);
public Completionstage<Void> thenAcceptAsync (Consumer < ? super T > action);
public Completionstage<Void> thenAcceptAsync (consumer < ? super T > action, Executor executor);
 
public CompletionStage<Void> thenRun (Runnable action);
public Completionstage<Void> thenRunAsync (Runnable action);
public Completionstage<Void> thenRunAsync (Runnable action, Executor executor);
  • thenApply方法:当一个线程依赖另一个线程时,获取上一个任务返回的结果,并返回当前任务的返回值

  • thenAccept方法:消费处理结果,接收到结果后进行处理,并消费掉,没有返回结果

  • thenRun方法:只要上面的任务执行完,就开始执行thenRun,只有处理完任务后,执行thenRun的后续操作,不能获取上一步的执行结果

  • 带有Async默认是异步执行的,同之前。以上都要前置任务成功完成。Function<? super T,? extends U>

  • T:上一个任务返回的结果类型 U:当前任务的返回值类型

代码如下:

 public static void main(String[] args) throws ExecutionException, InterruptedException {
        System.out.println("---------主线程开始--------");
        CompletableFuture<String> thenApplyAsync  = CompletableFuture.supplyAsync(() -> {
            System.out.println("thenApplyAsync 当前线程:" + Thread.currentThread().getId());
            int i = 10 / 2;
            System.out.println("thenApplyAsync 当前运行结果:" + i);
            return i;
        }, executor).thenApplyAsync(res->{
            System.out.println("thenApplyAsync任务2启动了。。。。"+res);
            return "hello"+res;
        },executor);
        //拿到结果
        String s = thenApplyAsync.get();
        System.out.println("thenApplyAsync返回结果:"+s);
        //thenAcceptAsync能接收上一步的返回结果,但是没有返回值
        CompletableFuture<Void> thenAcceptAsync = CompletableFuture.supplyAsync(()->{
            System.out.println("thenAcceptAsync当前线程:" + Thread.currentThread().getId());
            int i = 10 / 5;
            System.out.println("thenAcceptAsync当前运行结果:" + i);
            return i;
        },executor).thenAcceptAsync(res->{
            System.out.println("thenAcceptAsync任务2启动了。。。。" + res);
        },executor);

        // 4.3、thenRun 不能获取得到上一步的执行结果
        CompletableFuture<Void> thenRunAsync = CompletableFuture.supplyAsync(() -> {
            System.out.println("thenRunAsync当前线程:" + Thread.currentThread().getId());
            int i = 10 / 5;
            System.out.println("thenRunAsync当前运行结果:" + i);
            return i;
        }, executor).thenRunAsync(() -> {
            System.out.println("thenRunAsync任务2启动了。。。。");
        }, executor);
    }

两任务组合-都要完成

两个任务都必须完成,触发该任务

  • runAfterBoth

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

public CompletableFuture<Void> runAfterBoth(CompletionStage<?> other,Runnable action);
public CompletableFuture<Void> runAfterBothAsync(CompletionStage<?> other,Runnable action);
public CompletableFuture<Void> runAfterBothAsync(CompletionStage<?> other,Runnable action,Executor 
  • thenAccetpBoth

组合两个 future,获取两个future任务的返回结果,然后处理任务,没有返回结果

public <U> CompletableFuture<Void> thenAcceptBoth(CompletionStage<? extends U> other,BiConsumer<? super T, ? super U> action);
public <U> CompletableFuture<Void> thenAcceptBothAsync(CompletionStage<? extends U> other,BiConsumer<? super T, ? super U> action);
public <U> CompletableFuture<Void> thenAcceptBothAsync(CompletionStage<? extends U> other,BiConsumer<? super T, ? super U> action,     Executor executor);
  • thenCombine

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

public <U,V> CompletableFuture<V> thenCombine(CompletionStage<? extends U> other,BiFunction<? super T,? super U,? extends V> fn);
public <U,V> CompletableFuture<V> thenCombineAsync(CompletionStage<? extends U> other,BiFunction<? super T,? super U,? extends V> fn);
public <U,V> CompletableFuture<V> thenCombineAsync(CompletionStage<? extends U> other,BiFunction<? super T,? super U,? extends V> fn,Executor executor);

代码如下:

 public static void main(String[] args) throws ExecutionException, InterruptedException {
        System.out.println("---------主线程开始--------");
        CompletableFuture<Object> future01 = CompletableFuture.supplyAsync(()->{
            System.out.println("------任务线程1-----"+Thread.currentThread().getId());
            int i = 10/5;
            System.out.println("----任务线程1结束");
            return i;
        },executor);
        CompletableFuture<Object> future02 = CompletableFuture.supplyAsync(()->{
            System.out.println("------任务线程2-----"+Thread.currentThread().getId());
            try {
                Thread.sleep(3000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println("任务线程2结束");
            return "hello";
        },executor);
        //不能得到两个任务的结果,也没有返回值
        future01.runAfterBothAsync(future02,()->{
            System.out.println("----runAfterBothAsync任务三开始---");
        },executor);
        //能得到两个任务的结果,但是没有返回值
        future01.thenAcceptBothAsync(future02,(r1,r2)->{
            System.out.println("----thenAcceptBothAsync任务三开始。。。之前的结果"+r1+":"+r2);
        },executor);
        //得到两个任务的参数并返回结果
        CompletableFuture<String> thenCombineAsync = future01.thenCombineAsync(future02,(r1,r2)->{
            System.out.println("----thenCombineAsync任务三开始。。。之前的结果" + r1 + ":" + r2);
            return r1 + ":" + r2 + "->无敌是多么寂寞";
        },executor);
        System.out.println("thenCombineAsync返回结果:" + thenCombineAsync.get());
        System.out.println("---------主线程结束--------");
    }

两任务组合-只要有一个任务完成就执行第三个

当两个任务中,任意一个任务执行完的时候,执行任务

  • runAfterEither方法

两个任务有一个执行完,不需要处理结果,处理任务也没有返回值

public CompletableFuture<Void> runAfterEither(CompletionStage<?> other,Runnable action);
public CompletableFuture<Void> runAfterEitherAsync(CompletionStage<?> other,Runnable action);
public CompletableFuture<Void> runAfterEitherAsync(CompletionStage<?> other,Runnable action,Executor executor);
  • acceptEither

两个任务有一个执行完,获取它的返回值,处理任务,没有新的返回值

public CompletableFuture<Void> acceptEither(CompletionStage<? extends T> other,Consumer<? super T> action);
public CompletableFuture<Void> acceptEitherAsync(CompletionStage<? extends T> other,Consumer<? super T> action);
public CompletableFuture<Void> acceptEitherAsync(CompletionStage<? extends T> other,Consumer<? super
  • applyToEither方法

两个任务有一个处理完成,获取他的返回值,处理任务并返回新的返回值

public <U> CompletableFuture<U> applyToEither(CompletionStage<? extends T> other,Function<? super T, U> fn);
public <U> CompletableFuture<U> applyToEitherAsync(CompletionStage<? extends T> other,Function<? super T, U> fn);
public <U> CompletableFuture<U> applyToEitherAsync(CompletionStage<? extends T> other,Function<? sup

 代码如下:

    public static void main(String[] args) throws ExecutionException, InterruptedException {
        System.out.println("---------主线程开始--------");
        CompletableFuture<Object> future001 = CompletableFuture.supplyAsync(() -> {
            System.out.println("future001任务1线程:" + Thread.currentThread().getId());
            int i = 10 / 5;
            System.out.println("future001任务1线程结束");
            return i;
        }, executor);
        CompletableFuture<Object> future002 = CompletableFuture.supplyAsync(() -> {
            System.out.println("任务2线程:" + Thread.currentThread().getId());
            try {
                Thread.sleep(3000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println("future002任务2线程结束");
            return "hello";
        }, executor);

        //runAfterEitherAsync 不感知结果,自己也无返回值
        future001.runAfterEitherAsync(future002, () -> {
            System.out.println("runAfterEitherAsync任务三开始。。。");
        }, executor);

        //accetpEitherAsync 感知结果,自己没有返回值
        future001.acceptEitherAsync(future002, (res) -> {
            System.out.println("acceptEitherAsync任务三开始。。。" + res);
        }, executor);

        //applyToEitherAsync
        CompletableFuture<String> stringCompletableFuture = future001.applyToEitherAsync(future002, (res) -> {
            System.out.println("applyToEitherAsync任务三开始。。。" + res);
            return res.toString() + "-> haha";
        }, executor);
        System.out.println("applyToEitherAsync返回结果:" + stringCompletableFuture.get());
        System.out.println("---------主线程结束--------");
    }
  • thenCompose

thenCompose方法,允许你对两个CompletionStage 进行流水线操作,第一个操作完成时,将其结果作为参数传递给第二个操作。

public <U> CompletableFuture<U> thenCompose(Function<? super T, ? extends CompletionStage<U>> fn);
public <U> CompletableFuture<U> thenComposeAsync(Function<? super T, ? extends CompletionStage<U>> fn) ;
public <U> CompletableFuture<U> thenComposeAsync(Function<? super T, ? extends CompletionStage

多任务组合
public static completableFuture<Void> all0f(completableFuture<?>... cfs);
public static completableFuture<Obiect> anyof(completableFuture<?>... cfs);
  • allOf:等待所有任务完成

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

allOf代码:

 public static void main(String[] args) throws ExecutionException, InterruptedException {
        System.out.println("---------主线程开始--------");
        CompletableFuture<String> futureAttr = CompletableFuture.supplyAsync(() -> {
            System.out.println("查询商品的属性");
            return "黑色+256g";
        }, executor);

        CompletableFuture<String> futureImg = CompletableFuture.supplyAsync(() -> {
            try {
                Thread.sleep(3000);
                System.out.println("查询商品的图片信息");
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            return "hello.jpg";
        }, executor);

        CompletableFuture<String> futureDesc = CompletableFuture.supplyAsync(() -> {
            System.out.println("查询商品的介绍");
            return "华为";
        }, executor);

        CompletableFuture<Void> allOf = CompletableFuture.allOf(futureAttr, futureDesc, futureImg);
        allOf.get();//等待所有线程执行完
        System.out.println("allOf获取结果:" +  futureAttr.get() + "=>" + futureImg.get() + "=>" + futureDesc.get());
        System.out.println("---------主线程结束--------");
    }

 anyOf代码:

  public static void main(String[] args) throws ExecutionException, InterruptedException {
        System.out.println("---------主线程开始--------");
        CompletableFuture<String> futureAttr = CompletableFuture.supplyAsync(() -> {
            System.out.println("查询商品的属性");
            return "黑色+256g";
        }, executor);

        CompletableFuture<String> futureImg = CompletableFuture.supplyAsync(() -> {
            try {
                Thread.sleep(3000);
                System.out.println("查询商品的图片信息");
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            return "hello.jpg";
        }, executor);

        CompletableFuture<String> futureDesc = CompletableFuture.supplyAsync(() -> {
            System.out.println("查询商品的介绍");
            return "华为";
        }, executor);

        CompletableFuture<Object> future = CompletableFuture.anyOf(futureAttr, futureDesc, futureImg);
        future.get();
        System.out.println("anyOf获取结果:" +  futureAttr.get() + "=>" + futureImg.get() + "=>" + futureDesc.get());
        System.out.println("---------主线程结束--------");
    }

附:线程池代码配置

yml:

#线程池属性的配置
test:
  thread:
    core: 20
    max-size: 200
    keep-alive-time: 10

新建配置类  

@Data
@Component
@ConfigurationProperties(prefix = "test.thread")
public class ThreadPoolConfigProperties {
    private Integer core;
    private Integer maxSize;
    private Integer keepAliveTime;
}

线程池配置,获取线程池的属性值这里直接调用与配置文件相对应的属性配置类

//如果ThreadPoolConfigProperities.class类上没有加上@Component注解
// 那么我们在需要配置类里开启属性配置的类加载到容器
//@EnableConfigurationProperties(ThreadPoolConfigProperties.class)
@Configuration
public class MyThreadConfig {
    @Bean
    public ThreadPoolExecutor threadPoolExecutor(ThreadPoolConfigProperties pool) {
        return new ThreadPoolExecutor(pool.getCore(),
                pool.getMaxSize(),
                pool.getKeepAliveTime(),
                TimeUnit.SECONDS,
                new LinkedBlockingQueue<>(100000),
                Executors.defaultThreadFactory(),
                new ThreadPoolExecutor.AbortPolicy());

    }
}

为了使我们的任务进行的更快,我们可以让查询的各个子任务线程执行,但是由于各个任务之间可能有依赖的一些关系,因此就涉及到了异步编排.

根据我们的业务需求,选择合适的编排,不需要死记硬背,主要还是在业务上。

Java中,多线程异步编排通常涉及到使用并发库,如`java.util.concurrent`包提供的工具。其中一些关键组件包括: 1. **Future和Callable**: `Callable`接口用于异步计算任务,它返回一个`Future`对象,可以获取计算结果或检查是否完成。你可以通过提交`Callable`到`ExecutorService`来启动任务,并通过`Future.get()`阻塞等待结果。 2. **ExecutorService**: 这是一个服务,负责管理和调度提交给它的Runnable或Callable任务。常见的实现有`ThreadPoolExecutor`, `ScheduledExecutorService`等。 3. **Thread池** (`ThreadPoolExecutor`): 提供一组预先创建的线程,可以高效地处理大量并发任务,避免频繁创建销毁线程的开销。 4. **CompletableFuture**: 是Java 8引入的一个高级API,它提供了更简洁的方式来处理异步操作的结果。可以链式调用 `.thenApply()`, `.thenAccept()`, `.thenRun()` 等方法来组织复杂的异步流程。 5. **异步回调**: 当你需要在某个操作完成后立即执行其他操作时,可以使用`Runnable`和`Consumer`接口,它们提供了一种简单的回调机制。 6. **FutureTask**: 可以将一个Callable封装成一个Future,这使得Callable的任务能够像Runnable一样在ExecutorService中运行。 异步编程有助于提高系统的响应性和吞吐量,因为任务可以在后台线程中并行执行,而主线程则继续处理用户交互。然而,需要小心管理资源和同步问题,以防数据竞争和死锁。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值