1. Tổng quan về khung Executor
Khung Executor phân tách ứng dụng đa luồng Java thành các tác vụ riêng biệt, giao các tác vụ này cho các luồng xử lý và thu thập kết quả thực thi
1.1 Thành phần chính
- Giao diện tác vụ: Runnable và Callable - định nghĩa các phương thức cần triển khai để tạo tác vụ
- Giao diện thực thi: Executor và ExecutorService - quản lý việc chạy các tác vụ
- Kết quả thực thi: Future và FutureTask - biểu diễn kết quả bất đồng bộ
ThreadPoolExecutor là lớp cốt lõi thực hiện quản lý pool luồng, còn ScheduledThreadPoolExecutor hỗ trợ thực thi theo lịch trình với độ trễ xác định
2. Phân tích ThreadPoolExecutor
Khởi tạo thông qua lớp tiện ích Executors với 3 loại chính:
- SingleThreadExecutor: Duy trì 1 luồng duy nhất
- FixedThreadPool: Giới hạn số lượng luồng cố định
- CachedThreadPool: Tự động mở rộng pool theo nhu cầu
2.1 FixedThreadPool
public static ExecutorService taoFixedThreadPool(int soLuongThread, ThreadFactory factory) {
return new ThreadPoolExecutor(
soLuongThread,
soLuongThread,
0L, TimeUnit.MILLISECONDS,
new LinkedBlockingQueue<>(),
factory
);
}
Đặc điểm:
- Sử dụng hàng đợi liên kết không giới hạn LinkedBlockingQueue
- Giữ nguyên kích thước pool (corePool = maxPool)
- Không áp dụng chiến lược từ chối tác vụ nhờ hàng đợi vô hạn
- Luồng rảnh sẽ lấy tác vụ từ hàng đợi sau khi xử lý xong nhiệm vụ trước
2.2 SingleThreadExecutor
public static ExecutorService taoSingleThreadExecutor(ThreadFactory factory) {
return new FinalizableDelegatedExecutorService(
new ThreadPoolExecutor(
1, 1,
0L, TimeUnit.MILLISECONDS,
new LinkedBlockingQueue<>(),
factory
)
);
}
Giống FixedThreadPool nhưng chỉ duy trì 1 luồng, đảm bảo thứ tự thực thi tuần tự
2.3 CachedThreadPool
public static ExecutorService taoCachedThreadPool(ThreadFactory factory) {
return new ThreadPoolExecutor(
0, Integer.MAX_VALUE,
60L, TimeUnit.SECONDS,
new SynchronousQueue<>(),
factory
);
}
Cơ chế hoạt động:
- Tạo luồng mới khi hàng đợi SynchronousQueue đầy
- Luồng rảnh sẽ tồn tại tối đa 60 giây trước khi bị huỷ
- Hiệu quả với tác vụ ngắn hạn nhưng tiềm ẩn nguy cơ tiêu tốn tài nguyên khi tải cao
3. FutureTask - Quản lý kết quả bất đồng bộ
FutureTask kết hợp cả giao diện Future và Runnable, có 3 trạng thái:
- Chưa bắt đầu (trước khi gọi run)
- Đang chạy (trong phương thức run)
- Hoàn thành (kết thúc thành công/thất bại)
3.1 Hành vi khi gọi phương thức
- get(): Chặn luồng gọi cho đến khi có kết quả
- cancel(true): Ngắt luồng đang thực thi
- cancel(false): Cho phép luồng hoàn thành tác vụ
3.2 Cơ chế triển khai
FutureTask được xây dựng dựa trên Abstract Queued Synchronizer (AQS) - cơ chế đồng bộ hóa nền tảng của Java