×

Cách cài đặt CompletableFuture để lập trình bất đồng bộ trong Java

Bài viết này sẽ giúp các lập trình viên Java hiểu rõ cách sử dụng CompletableFuture để thực hiện lập trình bất đồng bộ. CompletableFuture là một phần của Java Concurrency API, cho phép bạn viết mã không đồng bộ với cú pháp tiện lợi và dễ hiểu. Thông qua những ví dụ và hướng dẫn cụ thể, bạn sẽ nắm được các khái niệm cơ bản tới các kỹ thuật nâng cao khi làm việc với CompletableFuture.

Tại sao nên sử dụng CompletableFuture?

Trước kia, lập trình bất đồng bộ trong Java chủ yếu dựa vào Thread và Runnable, điều này có thể tạo ra mã khó đọc và quản lý. CompletableFuture mang lại một cách tiếp cận trực quan hơn bằng cách sử dụng các phương thức kết hợp và xử lý khi một tác vụ hoàn thành.

Ưu điểm của CompletableFuture

  1. Dễ đọc và dễ bảo trì: Thay vì quản lý nhiều luồng, bạn có thể kết hợp các tác vụ bất đồng bộ một cách mạch lạc.
  2. Hỗ trợ các thao tác kết hợp: CompletableFuture cho phép bạn kết hợp nhiều tác vụ bất đồng bộ vào một chuỗi logic.
  3. Xử lý ngoại lệ: CompletableFuture có khả năng xử lý các ngoại lệ xảy ra trong quá trình thực hiện một tác vụ.

Các khái niệm cơ bản về CompletableFuture

Cách khởi tạo CompletableFuture

Bạn có thể khởi tạo một CompletableFuture bằng nhiều cách khác nhau. Dưới đây là một ví dụ đơn giản:

CompletableFuture<String> future = new CompletableFuture<>();

Trong trường hợp này, CompletableFuture sẽ được hoàn thành khi bạn gọi phương thức complete.

Hoàn thành CompletableFuture

Để hoàn thành một CompletableFuture, bạn có thể sử dụng phương thức complete:

future.complete("Kết quả");

Khi bạn gọi complete, bất kỳ lệnh gọi nào đến get trên CompletableFuture sẽ nhận giá trị "Kết quả".

Lập trình bất đồng bộ với CompletableFuture

Sử dụng phương thức supplyAsync

Một trong những cách phổ biến để khởi tạo và thực hiện công việc bất đồng bộ với CompletableFuture là sử dụng phương thức supplyAsync:

CompletableFuture<String> future = CompletableFuture.supplyAsync(() -> {
    // Thực hiện công việc nặng
    return "Kết quả từ tác vụ bất đồng bộ";
});

Chờ và lấy kết quả

Bạn có thể chờ cho CompletableFuture hoàn thành và lấy kết quả bằng phương thức get:

try {
    String result = future.get();
    System.out.println(result);
} catch (InterruptedException | ExecutionException e) {
    e.printStackTrace();
}

Kết hợp nhiều CompletableFuture

Nếu bạn muốn kết hợp nhiều CompletableFuture, bạn có thể sử dụng phương thức thenCombine:

CompletableFuture<Integer> future1 = CompletableFuture.supplyAsync(() -> 5);
CompletableFuture<Integer> future2 = CompletableFuture.supplyAsync(() -> 10);

CompletableFuture<Integer> combinedFuture = future1.thenCombine(future2, (a, b) -> a + b);

Xử lý ngoại lệ

Trong lập trình bất đồng bộ, việc xử lý ngoại lệ là rất quan trọng. CompletableFuture cung cấp phương thức exceptionally để xử lý các ngoại lệ phát sinh trong quá trình thực hiện tác vụ:

CompletableFuture<Integer> futureWithException = CompletableFuture.supplyAsync(() -> {
    throw new RuntimeException("Một lỗi xảy ra");
}).exceptionally(ex -> {
    System.out.println("Xử lý lỗi: " + ex.getMessage());
    return 0; // Trả giá trị thay thế
});

Sử dụng phương thức allOf

Khi bạn có một số CompletableFuture mà muốn chờ tất cả hoàn thành trước khi tiếp tục, bạn có thể sử dụng phương thức allOf:

CompletableFuture<Void> allFutures = CompletableFuture.allOf(future1, future2);
allFutures.join(); // Chờ cho tất cả hoàn thành

Thực hành với ví dụ cụ thể

Dưới đây là một ví dụ thực tế hoàn chỉnh, mô phỏng một tác vụ tải dữ liệu từ một nguồn bên ngoài và xử lý chúng:

import java.util.concurrent.CompletableFuture;

public class Example {
    public static void main(String[] args) {
        CompletableFuture<String> future = CompletableFuture.supplyAsync(() -> {
            // Giả lập tải dữ liệu
            try {
                Thread.sleep(2000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            return "Dữ liệu đã tải";
        });

        CompletableFuture<String> processedFuture = future.thenApply(data -> {
            return "Xử lý: " + data;
        });

        processedFuture.thenAccept(System.out::println);
    }
}

Giải thích mã

Trong ví dụ này, chúng ta tạo một CompletableFuture để tải dữ liệu bất đồng bộ. Sau khi dữ liệu được tải thành công, chúng ta sử dụng thenApply để xử lý dữ liệu và cuối cùng in ra kết quả.

Kết luận

CompletableFuture mang lại sức mạnh vượt trội cho lập trình bất đồng bộ trong Java. Với cú pháp dễ hiểu và khả năng kết hợp mạnh mẽ, bạn có thể tạo ra những ứng dụng động và nhẹ nhàng hơn. Việc nắm vững CompletableFuture sẽ giúp bạn tối ưu hóa hiệu suất ứng dụng và cải thiện trải nghiệm của người dùng.

Hy vọng bài viết này đã giúp bạn có cái nhìn tổng quát và rõ ràng về cách cài đặt và sử dụng CompletableFuture trong lập trình Java. Hãy thử nghiệm và áp dụng nó vào dự án của bạn để nâng cao hiệu suất lập trình!

Comments