CyStack logo
  • Sản phẩm & Dịch vụ
  • Giải pháp
  • Bảng giá
  • Công ty
  • Tài liệu
Vi

vi

Mục lục

Trang chủBlogHướng dẫn sử dụng FutureT...
Java

Hướng dẫn sử dụng FutureTask trong Java qua ví dụ cụ thể

4 phút đọc25/08/2025
CyStack Author
Bao Tran

Web Developer

0 lượt xem
Reading Time: 4 minutes

Cách đây không lâu, tôi đã viết một bài về các interface Callable và Future trong Java, cho phép chúng ta vừa tận dụng lợi ích xử lý song song của luồng (thread), vừa có khả năng trả về giá trị cho chương trình gọi.

 FutureTask trong Java

FutureTask trong Java là một triển khai cụ thể cơ bản của interface Future và cung cấp khả năng xử lý bất đồng bộ. Lớp này có các phương thức để khởi chạy hoặc hủy một tác vụ, đồng thời cho phép kiểm tra trạng thái của FutureTask như đã hoàn tất hay đã bị hủy.

Để tạo một FutureTask, chúng ta cần một đối tượng Callable. Sau đó, có thể sử dụng Java Thread Pool Executor để xử lý các tác vụ này một cách bất đồng bộ.

Sau đây ví dụ về FutureTask qua một chương trình đơn giản. Vì FutureTask yêu cầu một đối tượng Callable, chúng ta sẽ tạo một lớp triển khai Callable đơn giản.

package com.journaldev.threads;

import java.util.concurrent.Callable;

public class MyCallable implements Callable {

	private long waitTime;
	
	public MyCallable(int timeInMillis){
		this.waitTime=timeInMillis;
	}
	@Override
	public String call() throws Exception {
		Thread.sleep(waitTime);
        //return the thread name executing this callable task
        return Thread.currentThread().getName();
	}

}

Đây là một chương trình ví dụ về FutureTask, minh họa các phương thức thường được sử dụng của nó.

package com.journaldev.threads;

import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.FutureTask;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;

public class FutureTaskExample {

	public static void main(String[] args) {
		MyCallable callable1 = new MyCallable(1000);
		MyCallable callable2 = new MyCallable(2000);

		FutureTask futureTask1 = new FutureTask(callable1);
		FutureTask futureTask2 = new FutureTask(callable2);

		ExecutorService executor = Executors.newFixedThreadPool(2);
		executor.execute(futureTask1);
		executor.execute(futureTask2);
		
		while (true) {
			try {
				if(futureTask1.isDone() && futureTask2.isDone()){
					System.out.println("Done");
					//shut down executor service
					executor.shutdown();
					return;
				}
				
				if(!futureTask1.isDone()){
				//wait indefinitely for future task to complete
				System.out.println("FutureTask1 output="+futureTask1.get());
				}
				
				System.out.println("Waiting for FutureTask2 to complete");
				String s = futureTask2.get(200L, TimeUnit.MILLISECONDS);
				if(s !=null){
					System.out.println("FutureTask2 output="+s);
				}
			} catch (InterruptedException | ExecutionException e) {
				e.printStackTrace();
			}catch(TimeoutException e){
				//do nothing
			}
		}
		
	}

}

Khi chạy chương trình trên, bạn sẽ thấy nó không in ra gì ngay lập tức. Đó là vì phương thức get() của FutureTask sẽ chặn luồng hiện tại cho đến khi tác vụ hoàn thành, sau đó mới trả về đối tượng kết quả. Ngoài ra, get() còn có một phiên bản nạp chồng phương thức cho phép chỉ chờ trong một khoảng thời gian nhất định, và chúng ta đang sử dụng nó cho futureTask2. Cũng cần lưu ý việc sử dụng phương thức isDone() để đảm bảo chương trình sẽ kết thúc sau khi tất cả các tác vụ đã được thực thi.

Kết quả đầu ra của chương trình trên sẽ là:

FutureTask1 output=pool-1-thread-1
Waiting for FutureTask2 to complete
Waiting for FutureTask2 to complete
Waiting for FutureTask2 to complete
Waiting for FutureTask2 to complete
Waiting for FutureTask2 to complete
FutureTask2 output=pool-1-thread-2
Done

Thoạt nhìn, FutureTask có vẻ không mang lại lợi ích gì nổi bật. Tuy nhiên, nó trở nên hữu ích khi chúng ta muốn ghi đè một vài phương thức của interface Future mà không cần phải triển khai toàn bộ các phương thức của interface này.

Cách đây không lâu, tôi đã viết một bài về các interface Callable và Future trong Java, cho phép chúng ta vừa tận dụng lợi ích xử lý song song của luồng (thread), vừa có khả năng trả về giá trị cho chương trình gọi.

FutureTask là một triển khai cụ thể cơ bản của interface Future và cung cấp khả năng xử lý bất đồng bộ. Lớp này có các phương thức để khởi chạy hoặc hủy một tác vụ, đồng thời cho phép kiểm tra trạng thái của FutureTask như đã hoàn tất hay đã bị hủy.

Để tạo một FutureTask, chúng ta cần một đối tượng Callable. Sau đó, có thể sử dụng Java Thread Pool Executor để xử lý các tác vụ này một cách bất đồng bộ.

Sau đây ví dụ về FutureTask qua một chương trình đơn giản. Vì FutureTask yêu cầu một đối tượng Callable, chúng ta sẽ tạo một lớp triển khai Callable đơn giản.

package com.journaldev.threads;

import java.util.concurrent.Callable;

public class MyCallable implements Callable {

	private long waitTime;
	
	public MyCallable(int timeInMillis){
		this.waitTime=timeInMillis;
	}
	@Override
	public String call() throws Exception {
		Thread.sleep(waitTime);
        //return the thread name executing this callable task
        return Thread.currentThread().getName();
	}

}

Đây là một chương trình ví dụ về FutureTask, minh họa các phương thức thường được sử dụng của nó.

package com.journaldev.threads;

import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.FutureTask;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;

public class FutureTaskExample {

	public static void main(String[] args) {
		MyCallable callable1 = new MyCallable(1000);
		MyCallable callable2 = new MyCallable(2000);

		FutureTask futureTask1 = new FutureTask(callable1);
		FutureTask futureTask2 = new FutureTask(callable2);

		ExecutorService executor = Executors.newFixedThreadPool(2);
		executor.execute(futureTask1);
		executor.execute(futureTask2);
		
		while (true) {
			try {
				if(futureTask1.isDone() && futureTask2.isDone()){
					System.out.println("Done");
					//shut down executor service
					executor.shutdown();
					return;
				}
				
				if(!futureTask1.isDone()){
				//wait indefinitely for future task to complete
				System.out.println("FutureTask1 output="+futureTask1.get());
				}
				
				System.out.println("Waiting for FutureTask2 to complete");
				String s = futureTask2.get(200L, TimeUnit.MILLISECONDS);
				if(s !=null){
					System.out.println("FutureTask2 output="+s);
				}
			} catch (InterruptedException | ExecutionException e) {
				e.printStackTrace();
			}catch(TimeoutException e){
				//do nothing
			}
		}
		
	}

}

Khi chạy chương trình trên, bạn sẽ thấy nó không in ra gì ngay lập tức. Đó là vì phương thức get() của FutureTask sẽ chặn luồng hiện tại cho đến khi tác vụ hoàn thành, sau đó mới trả về đối tượng kết quả. Ngoài ra, get() còn có một phiên bản nạp chồng phương thức cho phép chỉ chờ trong một khoảng thời gian nhất định, và chúng ta đang sử dụng nó cho futureTask2. Cũng cần lưu ý việc sử dụng phương thức isDone() để đảm bảo chương trình sẽ kết thúc sau khi tất cả các tác vụ đã được thực thi.

Kết quả đầu ra của chương trình trên sẽ là:

FutureTask1 output=pool-1-thread-1
Waiting for FutureTask2 to complete
Waiting for FutureTask2 to complete
Waiting for FutureTask2 to complete
Waiting for FutureTask2 to complete
Waiting for FutureTask2 to complete
FutureTask2 output=pool-1-thread-2
Done

Thoạt nhìn, FutureTask có vẻ không mang lại lợi ích gì nổi bật. Tuy nhiên, nó trở nên hữu ích khi chúng ta muốn ghi đè một vài phương thức của interface Future mà không cần phải triển khai toàn bộ các phương thức của interface này.

Về tác giả

Bao Tran
Bao TranWeb Developer

I’m passionate about web development and sharing my insights through articles, with over 8 years of experience. I hope these sharings inspire you and help build a strong web development community. @#@ Tôi đam mê phát triển web và chia sẻ những hiểu biết của mình thông qua các bài viết, với hơn 8 năm kinh nghiệm. Tôi hy vọng những chia sẻ này sẽ truyền cảm hứng cho các bạn và giúp xây dựng một cộng đồng phát triển web mạnh mẽ.

Cập nhật thông tin mới nhấtNhận các thông tin mới nhất về mối đe dọa, báo cáo an ninh mạng từ CyStack về hòm thư điện tử của bạn

Thảo luận (0)

Đăng nhập để thảo luận

Bài viết liên quan