🌟 Giới thiệu
Trong bài viết này, chúng ta sẽ khám phá cách xây dựng một dịch vụ sản phẩm không đồng bộ bằng cách sử dụng CompletableFuture trong Java. Bằng cách này, chúng ta có thể tối ưu hóa hiệu suất và đảm bảo rằng dịch vụ có thể xử lý nhiều yêu cầu đồng thời một cách hiệu quả. Đây là một kỹ thuật rất hữu ích trong môi trường microservices, nơi mà việc gọi đến nhiều dịch vụ khác nhau là điều phổ biến.
🎯 Tình huống
Chúng ta đang xây dựng một dịch vụ để lấy thông tin sản phẩm với các thành phần sau:
- Chi tiết sản phẩm (tốn khoảng 1 giây)
- Thông tin giá cả (tốn khoảng 2 giây, đôi khi chậm → sử dụng timeout và fallback)
- Đánh giá (lấy đồng thời, sau đó kết hợp)
Cuối cùng, chúng ta sẽ kết hợp tất cả thông tin này thành một chuỗi phản hồi duy nhất.
✅ Mã ví dụ đầy đủ
Dưới đây là mã ví dụ để thực hiện dịch vụ sản phẩm không đồng bộ:
java
import java.util.concurrent.*;
public class AsyncProductService {
private static final ExecutorService executor = Executors.newFixedThreadPool(5);
public static void main(String[] args) throws Exception {
// Bước 1: Lấy chi tiết sản phẩm
CompletableFuture<String> productFuture = CompletableFuture.supplyAsync(() -> {
sleep(1000);
return "Sản phẩm: Laptop";
}, executor);
// Bước 2: Lấy giá (với timeout + fallback)
CompletableFuture<String> priceFuture = CompletableFuture.supplyAsync(() -> {
sleep(3000); // mô phỏng API chậm
return "Giá: $1200";
}, executor)
.completeOnTimeout("Giá: không có (fallback timeout)", 2, TimeUnit.SECONDS)
.exceptionally(ex -> "Giá: không có (fallback lỗi)");
// Bước 3: Lấy đánh giá (công việc đồng thời)
CompletableFuture<String> reviewsFuture = CompletableFuture.supplyAsync(() -> {
sleep(1500);
return "Đánh giá: ⭐⭐⭐⭐";
}, executor);
// Bước 4: Kết hợp sản phẩm + giá trước
CompletableFuture<String> productWithPrice =
productFuture.thenCombine(priceFuture, (product, price) -> product + ", " + price);
// Bước 5: Thêm đánh giá vào phản hồi cuối
CompletableFuture<String> finalResponse =
productWithPrice.thenCombine(reviewsFuture, (partial, reviews) -> partial + ", " + reviews);
// Bước 6: Chờ đợi và in kết quả cuối
System.out.println("Phản hồi cuối: " + finalResponse.get());
executor.shutdown();
}
private static void sleep(int ms) {
try { Thread.sleep(ms); } catch (InterruptedException e) {}
}
}
📝 Kết quả ví dụ
Khi chạy mã trên, bạn sẽ nhận được kết quả như sau:
Phản hồi cuối: Sản phẩm: Laptop, Giá: không có (fallback timeout), Đánh giá: ⭐⭐⭐⭐
Hoặc, nếu API giá phản hồi kịp thời:
Phản hồi cuối: Sản phẩm: Laptop, Giá: $1200, Đánh giá: ⭐⭐⭐⭐
⚡ Các khái niệm chính được trình bày
- Thực thi đồng thời →
supplyAsync+thenCombine - Pipeline phụ thuộc → sản phẩm trước, sau đó kết hợp với giá và đánh giá
- Khả năng phục hồi →
completeOnTimeout&exceptionally - Kiểm soát luồng → executor tùy chỉnh với 5 luồng
- Tổng hợp cuối cùng → tất cả các nhiệm vụ được gộp lại thành một
CompletableFuture
🛠️ Thực tiễn tốt nhất
- Luôn sử dụng
completeOnTimeoutvàexceptionallyđể đảm bảo rằng dịch vụ không bị treo trong trường hợp API chậm hoặc không phản hồi. - Sử dụng executor tùy chỉnh để kiểm soát số lượng luồng, giúp tối ưu hóa hiệu suất.
⚠️ Cạm bẫy thường gặp
- Không nên sử dụng
supplyAsyncmà không quản lý các luồng, điều này có thể dẫn đến việc sử dụng quá nhiều tài nguyên. - Đảm bảo rằng các nhiệm vụ không gây ra deadlock, đặc biệt khi kết hợp nhiều
CompletableFuture.
⚡ Mẹo hiệu suất
- Sử dụng
ExecutorServiceđể quản lý luồng một cách tối ưu và tránh tạo quá nhiều luồng không cần thiết. - Kiểm tra hiệu suất của từng API và điều chỉnh thời gian timeout cho hợp lý.
❓ Câu hỏi thường gặp
1. CompletableFuture là gì?
CompletableFuture là một lớp trong Java được sử dụng để xử lý các tác vụ bất đồng bộ một cách dễ dàng và hiệu quả.
2. Tôi có thể sử dụng CompletableFuture trong những tình huống nào?
Bạn có thể sử dụng CompletableFuture trong mọi tình huống cần thực hiện các tác vụ bất đồng bộ, ví dụ như gọi API, xử lý tệp, hoặc thực hiện các tác vụ lâu dài khác mà không làm treo ứng dụng.
🔗 Tài nguyên thêm
🌈 Kết luận
Bài viết này đã giới thiệu cách xây dựng một dịch vụ sản phẩm không đồng bộ sử dụng CompletableFuture trong Java, giúp tối ưu hóa hiệu suất và xử lý nhiều yêu cầu đồng thời. Hãy thử áp dụng kỹ thuật này vào dự án của bạn để nâng cao hiệu suất ứng dụng. Nếu bạn có bất kỳ câu hỏi nào, đừng ngần ngại để lại câu hỏi trong phần bình luận dưới đây!