Java concurrency (multi-threading)

1. ExecutorService

ExecutorService là một framework sinh ra với mục đích đơn giản hóa việc thực thi các task theo cơ chế bất đồng bộ. Về cơ bản ExecutorService tự động khởi tạo thread pool và cung cấp các API cho phép developer assigning task tới pool.

ExecutorService không tự động destroyed khi không có task nào thực thi. Nó sẽ alivewait for new work. Điều này cũng hữu ích trong một số trường hợp khi số lượng task là không cố định và không biết trước tại thời điểm compile. VD: 1 program SocketServer.

Trong các trường hợp khác sẽ không thể kiểm soát khi chương trình đã thực thi xong nhiệm vụ nhưng không thể dừng lại chỉ bởi ExecutorService  vẫn alive và tiếp tục wait for new work. Để tránh trường hợp này java cung cấp 2 API là shutdown() và shutdownNow()

shutDown() sẽ dừng việc tiếp nhận các task mới và shut down hoàn toàn sau khi những submitted task được thực thi.

shutdownNow() sẽ ngay lập tức destroy ExecutorService và trả lại danh sách các task đang đợi để thực thi. Developer cần quyết định sẽ làm gì với những task này.

Oracle khuyến cáo sử dụng cả 2 phương thức shutdown của ExecutorService. Sử dụng shutdown() trước để vô hiệu hóa việc tiếp nhận các task mới. Đợi trong 1 khoảng thời gian nhất định để toàn bộ các task được thực thi. Sau quãng thời gian này thực hiện lệnh shutdownNow()

 void shutdownAndAwaitTermination(ExecutorService pool) {
   pool.shutdown(); // Disable new tasks from being submitted
   try {
     // Wait a while for existing tasks to terminate
     if (!pool.awaitTermination(60, TimeUnit.SECONDS)) {
       pool.shutdownNow(); // Cancel currently executing tasks
       // Wait a while for tasks to respond to being cancelled
       if (!pool.awaitTermination(60, TimeUnit.SECONDS))
           System.err.println("Pool did not terminate");
     }
   } catch (InterruptedException ie) {
     // (Re-)Cancel if current thread also interrupted
     pool.shutdownNow();
     // Preserve interrupt status
     Thread.currentThread().interrupt();
   }
 }

awaitTermination(long timeout, TimeUnit unit) sẽ block thread cho đến khi toàn bộ task được thực thi sau lệnh shutdown()  hoặc khi hết thời gian đã định trước.

2. Futures and Callables

Trong trường hợp thread cần trả về 1 kết quả chúng ta cần implement interface  java.util.concurrent.Callable. Callable object cho phép trả về một giá trị sau khi task hoàn thành.  Sau khi submit object Callable tới ExecutorService sẽ nhận lại một object type java.util.concurrent.Future cho phép chờ lấy kết quả hoặc kiểm tra trạng thái thực thi task.

Callable<Long> task = new SampleCallable();
    Future<Long> result = executorService.submit(task);

    // A special blocking method
    // Calling the get() method while the task is still running will
    // cause execution to block until the task is properly executed and
    // the result is available.
    logger.debug("Result {}", result.get());
}
Advertisements

Trả lời

Mời bạn điền thông tin vào ô dưới đây hoặc kích vào một biểu tượng để đăng nhập:

WordPress.com Logo

Bạn đang bình luận bằng tài khoản WordPress.com Đăng xuất /  Thay đổi )

Google photo

Bạn đang bình luận bằng tài khoản Google Đăng xuất /  Thay đổi )

Twitter picture

Bạn đang bình luận bằng tài khoản Twitter Đăng xuất /  Thay đổi )

Facebook photo

Bạn đang bình luận bằng tài khoản Facebook Đăng xuất /  Thay đổi )

Connecting to %s