Java多线程工具CompletableFuture怎么使用

发布时间:2022-08-25 17:00:43 作者:iii
来源:亿速云 阅读:268

Java多线程工具CompletableFuture怎么使用

目录

  1. 引言
  2. CompletableFuture简介
  3. 创建CompletableFuture
  4. 异步任务处理
  5. 任务链式调用
  6. 异常处理
  7. 组合多个CompletableFuture
  8. 超时处理
  9. 实际应用场景
  10. 总结

引言

在现代软件开发中,多线程编程已经成为提高应用性能的重要手段之一。Java作为一门广泛使用的编程语言,提供了多种多线程工具来帮助开发者实现并发编程。其中,CompletableFuture是Java 8引入的一个强大的工具,用于处理异步任务和构建复杂的任务链。本文将详细介绍CompletableFuture的使用方法,并通过示例代码展示其在实际开发中的应用。

CompletableFuture简介

CompletableFuturejava.util.concurrent包中的一个类,它实现了Future接口,并提供了更丰富的功能来处理异步任务。与传统的Future相比,CompletableFuture不仅支持异步任务的执行,还允许开发者通过链式调用的方式组合多个任务,处理任务之间的依赖关系,以及处理任务执行过程中可能出现的异常。

创建CompletableFuture

在开始使用CompletableFuture之前,首先需要了解如何创建一个CompletableFuture对象。CompletableFuture提供了多种静态方法来创建实例。

1. 使用supplyAsync方法

supplyAsync方法用于创建一个异步任务,并返回一个CompletableFuture对象。该方法接受一个Supplier函数式接口作为参数,表示要执行的任务。

CompletableFuture<String> future = CompletableFuture.supplyAsync(() -> {
    // 模拟一个耗时任务
    try {
        Thread.sleep(1000);
    } catch (InterruptedException e) {
        e.printStackTrace();
    }
    return "Hello, CompletableFuture!";
});

2. 使用runAsync方法

runAsync方法用于创建一个异步任务,但不返回任何结果。该方法接受一个Runnable函数式接口作为参数。

CompletableFuture<Void> future = CompletableFuture.runAsync(() -> {
    // 模拟一个耗时任务
    try {
        Thread.sleep(1000);
    } catch (InterruptedException e) {
        e.printStackTrace();
    }
    System.out.println("Task completed.");
});

3. 使用completedFuture方法

completedFuture方法用于创建一个已经完成的CompletableFuture对象,并返回指定的结果。

CompletableFuture<String> future = CompletableFuture.completedFuture("Hello, CompletableFuture!");

异步任务处理

CompletableFuture的核心功能之一是处理异步任务。通过supplyAsyncrunAsync方法,我们可以轻松地将任务提交到线程池中执行,并在任务完成后获取结果或执行后续操作。

1. 获取任务结果

CompletableFuture提供了get方法来获取任务的结果。需要注意的是,get方法会阻塞当前线程,直到任务完成。

CompletableFuture<String> future = CompletableFuture.supplyAsync(() -> {
    // 模拟一个耗时任务
    try {
        Thread.sleep(1000);
    } catch (InterruptedException e) {
        e.printStackTrace();
    }
    return "Hello, CompletableFuture!";
});

String result = future.get();  // 阻塞等待任务完成
System.out.println(result);

为了避免阻塞当前线程,可以使用join方法,它与get方法类似,但不会抛出受检异常。

String result = future.join();  // 阻塞等待任务完成,不抛出受检异常
System.out.println(result);

2. 回调处理

CompletableFuture提供了多种回调方法来处理任务完成后的结果。常用的回调方法包括thenApplythenAcceptthenRun

thenApply方法

thenApply方法用于在任务完成后对结果进行处理,并返回一个新的CompletableFuture对象。

CompletableFuture<String> future = CompletableFuture.supplyAsync(() -> {
    // 模拟一个耗时任务
    try {
        Thread.sleep(1000);
    } catch (InterruptedException e) {
        e.printStackTrace();
    }
    return "Hello, CompletableFuture!";
});

CompletableFuture<String> newFuture = future.thenApply(result -> {
    return result.toUpperCase();
});

System.out.println(newFuture.join());  // 输出: HELLO, COMPLETABLEFUTURE!

thenAccept方法

thenAccept方法用于在任务完成后对结果进行处理,但不返回任何结果。

CompletableFuture<String> future = CompletableFuture.supplyAsync(() -> {
    // 模拟一个耗时任务
    try {
        Thread.sleep(1000);
    } catch (InterruptedException e) {
        e.printStackTrace();
    }
    return "Hello, CompletableFuture!";
});

future.thenAccept(result -> {
    System.out.println(result.toUpperCase());  // 输出: HELLO, COMPLETABLEFUTURE!
});

thenRun方法

thenRun方法用于在任务完成后执行一个操作,但不使用任务的结果。

CompletableFuture<String> future = CompletableFuture.supplyAsync(() -> {
    // 模拟一个耗时任务
    try {
        Thread.sleep(1000);
    } catch (InterruptedException e) {
        e.printStackTrace();
    }
    return "Hello, CompletableFuture!";
});

future.thenRun(() -> {
    System.out.println("Task completed.");  // 输出: Task completed.
});

任务链式调用

CompletableFuture的强大之处在于它支持链式调用,可以将多个任务串联起来,形成一个任务链。每个任务的输出可以作为下一个任务的输入。

1. 链式调用示例

CompletableFuture<String> future = CompletableFuture.supplyAsync(() -> {
    // 模拟一个耗时任务
    try {
        Thread.sleep(1000);
    } catch (InterruptedException e) {
        e.printStackTrace();
    }
    return "Hello";
}).thenApply(result -> {
    return result + ", CompletableFuture!";
}).thenApply(result -> {
    return result.toUpperCase();
});

System.out.println(future.join());  // 输出: HELLO, COMPLETABLEFUTURE!

2. 组合多个任务

CompletableFuture还提供了thenCombine方法,用于组合两个独立的CompletableFuture任务,并在它们都完成后对结果进行处理。

CompletableFuture<String> future1 = CompletableFuture.supplyAsync(() -> {
    // 模拟一个耗时任务
    try {
        Thread.sleep(1000);
    } catch (InterruptedException e) {
        e.printStackTrace();
    }
    return "Hello";
});

CompletableFuture<String> future2 = CompletableFuture.supplyAsync(() -> {
    // 模拟一个耗时任务
    try {
        Thread.sleep(1000);
    } catch (InterruptedException e) {
        e.printStackTrace();
    }
    return "CompletableFuture!";
});

CompletableFuture<String> combinedFuture = future1.thenCombine(future2, (result1, result2) -> {
    return result1 + ", " + result2;
});

System.out.println(combinedFuture.join());  // 输出: Hello, CompletableFuture!

异常处理

在异步任务执行过程中,可能会出现异常。CompletableFuture提供了多种方法来处理这些异常。

1. 使用exceptionally方法

exceptionally方法用于在任务执行过程中出现异常时,提供一个默认值或执行一些恢复操作。

CompletableFuture<String> future = CompletableFuture.supplyAsync(() -> {
    // 模拟一个耗时任务
    try {
        Thread.sleep(1000);
    } catch (InterruptedException e) {
        e.printStackTrace();
    }
    throw new RuntimeException("Task failed!");
}).exceptionally(ex -> {
    System.out.println("Exception: " + ex.getMessage());
    return "Default Value";
});

System.out.println(future.join());  // 输出: Default Value

2. 使用handle方法

handle方法用于在任务完成后处理结果或异常。无论任务是否成功完成,handle方法都会被调用。

CompletableFuture<String> future = CompletableFuture.supplyAsync(() -> {
    // 模拟一个耗时任务
    try {
        Thread.sleep(1000);
    } catch (InterruptedException e) {
        e.printStackTrace();
    }
    throw new RuntimeException("Task failed!");
}).handle((result, ex) -> {
    if (ex != null) {
        System.out.println("Exception: " + ex.getMessage());
        return "Default Value";
    }
    return result;
});

System.out.println(future.join());  // 输出: Default Value

组合多个CompletableFuture

在实际开发中,我们经常需要组合多个CompletableFuture任务,以便在它们都完成后执行某些操作。CompletableFuture提供了多种方法来组合多个任务。

1. 使用allOf方法

allOf方法用于等待多个CompletableFuture任务全部完成。

CompletableFuture<String> future1 = CompletableFuture.supplyAsync(() -> {
    // 模拟一个耗时任务
    try {
        Thread.sleep(1000);
    } catch (InterruptedException e) {
        e.printStackTrace();
    }
    return "Task 1";
});

CompletableFuture<String> future2 = CompletableFuture.supplyAsync(() -> {
    // 模拟一个耗时任务
    try {
        Thread.sleep(2000);
    } catch (InterruptedException e) {
        e.printStackTrace();
    }
    return "Task 2";
});

CompletableFuture<Void> allFutures = CompletableFuture.allOf(future1, future2);

allFutures.thenRun(() -> {
    System.out.println("All tasks completed.");
    System.out.println("Task 1 result: " + future1.join());
    System.out.println("Task 2 result: " + future2.join());
});

2. 使用anyOf方法

anyOf方法用于等待多个CompletableFuture任务中的任意一个完成。

CompletableFuture<String> future1 = CompletableFuture.supplyAsync(() -> {
    // 模拟一个耗时任务
    try {
        Thread.sleep(1000);
    } catch (InterruptedException e) {
        e.printStackTrace();
    }
    return "Task 1";
});

CompletableFuture<String> future2 = CompletableFuture.supplyAsync(() -> {
    // 模拟一个耗时任务
    try {
        Thread.sleep(2000);
    } catch (InterruptedException e) {
        e.printStackTrace();
    }
    return "Task 2";
});

CompletableFuture<Object> anyFuture = CompletableFuture.anyOf(future1, future2);

anyFuture.thenAccept(result -> {
    System.out.println("First completed task result: " + result);
});

超时处理

在某些情况下,我们希望为异步任务设置一个超时时间,以避免任务长时间阻塞。CompletableFuture本身并不直接支持超时处理,但可以通过结合ExecutorServiceScheduledExecutorService来实现。

1. 使用orTimeout方法(Java 9+)

从Java 9开始,CompletableFuture提供了orTimeout方法,用于为任务设置超时时间。

CompletableFuture<String> future = CompletableFuture.supplyAsync(() -> {
    // 模拟一个耗时任务
    try {
        Thread.sleep(2000);
    } catch (InterruptedException e) {
        e.printStackTrace();
    }
    return "Hello, CompletableFuture!";
}).orTimeout(1000, TimeUnit.MILLISECONDS);

try {
    System.out.println(future.join());
} catch (CompletionException ex) {
    System.out.println("Task timed out: " + ex.getMessage());
}

2. 使用completeOnTimeout方法(Java 9+)

completeOnTimeout方法用于在任务超时时提供一个默认值。

CompletableFuture<String> future = CompletableFuture.supplyAsync(() -> {
    // 模拟一个耗时任务
    try {
        Thread.sleep(2000);
    } catch (InterruptedException e) {
        e.printStackTrace();
    }
    return "Hello, CompletableFuture!";
}).completeOnTimeout("Default Value", 1000, TimeUnit.MILLISECONDS);

System.out.println(future.join());  // 输出: Default Value

实际应用场景

CompletableFuture在实际开发中有广泛的应用场景,特别是在需要处理多个异步任务的场景中。以下是一些常见的应用场景:

1. 并行处理多个任务

在某些情况下,我们需要并行处理多个任务,并在它们都完成后执行某些操作。CompletableFutureallOf方法非常适合这种场景。

CompletableFuture<String> future1 = CompletableFuture.supplyAsync(() -> {
    // 模拟一个耗时任务
    try {
        Thread.sleep(1000);
    } catch (InterruptedException e) {
        e.printStackTrace();
    }
    return "Task 1";
});

CompletableFuture<String> future2 = CompletableFuture.supplyAsync(() -> {
    // 模拟一个耗时任务
    try {
        Thread.sleep(2000);
    } catch (InterruptedException e) {
        e.printStackTrace();
    }
    return "Task 2";
});

CompletableFuture<Void> allFutures = CompletableFuture.allOf(future1, future2);

allFutures.thenRun(() -> {
    System.out.println("All tasks completed.");
    System.out.println("Task 1 result: " + future1.join());
    System.out.println("Task 2 result: " + future2.join());
});

2. 异步调用外部服务

在微服务架构中,我们经常需要异步调用外部服务,并在服务返回结果后进行处理。CompletableFuture可以帮助我们轻松实现这一需求。

CompletableFuture<String> future = CompletableFuture.supplyAsync(() -> {
    // 模拟调用外部服务
    try {
        Thread.sleep(1000);
    } catch (InterruptedException e) {
        e.printStackTrace();
    }
    return "Service Response";
});

future.thenAccept(response -> {
    System.out.println("Service response: " + response);
});

3. 任务依赖关系处理

在某些情况下,任务的执行顺序可能依赖于其他任务的结果。CompletableFuture的链式调用功能非常适合处理这种任务依赖关系。

CompletableFuture<String> future1 = CompletableFuture.supplyAsync(() -> {
    // 模拟一个耗时任务
    try {
        Thread.sleep(1000);
    } catch (InterruptedException e) {
        e.printStackTrace();
    }
    return "Task 1";
});

CompletableFuture<String> future2 = future1.thenApply(result -> {
    // 依赖于Task 1的结果
    return result + " -> Task 2";
});

System.out.println(future2.join());  // 输出: Task 1 -> Task 2

总结

CompletableFuture是Java中处理异步任务的强大工具,它提供了丰富的API来创建、组合和处理异步任务。通过CompletableFuture,开发者可以轻松实现复杂的任务链、处理任务之间的依赖关系、处理异常以及设置超时时间。在实际开发中,CompletableFuture广泛应用于并行处理、异步调用外部服务以及处理任务依赖关系等场景。掌握CompletableFuture的使用方法,将有助于提高应用的并发性能和开发效率。

通过本文的介绍,相信读者已经对CompletableFuture有了深入的了解,并能够在实际项目中灵活运用这一工具。希望本文能够帮助读者更好地理解和掌握Java多线程编程中的CompletableFuture

推荐阅读:
  1. Java8中CompletableFuture的使用方法
  2. Java多线程工具篇BlockingQueue的详解

免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。

java completablefuture

上一篇:vue中$emit怎么使用

下一篇:php如何将数组转为索引数组

相关阅读

您好,登录后才能下订单哦!

密码登录
登录注册
其他方式登录
点击 登录注册 即表示同意《亿速云用户服务条款》