웹사이트 검색

Java FutureTask 예제 프로그램


언젠가 나는 이것을 비동기적으로 처리하기 위해 Java Thread Pool Executor에 대한 게시물을 썼습니다. 간단한 프로그램으로 FutureTask의 예를 보자. FutureTask에는 콜러블 객체가 필요하므로 간단한 콜러블 구현을 생성합니다.

package com.journaldev.threads;

import java.util.concurrent.Callable;

public class MyCallable implements Callable<String> {

	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();
	}

}

다음은 FutureTask 메서드의 예이며 일반적으로 사용되는 FutureTask 메서드를 보여줍니다.

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<String> futureTask1 = new FutureTask<String>(callable1);
		FutureTask<String> futureTask2 = new FutureTask<String>(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
			}
		}
		
	}

}

위의 프로그램을 실행하면 FutureTask의 get() 메서드가 작업이 완료될 때까지 기다렸다가 출력 객체를 반환하기 때문에 일정 시간 동안 아무 것도 출력하지 않는 것을 알 수 있습니다. 지정된 시간만큼만 대기하는 오버로드된 메서드도 있으며 futureTask2에 사용하고 있습니다. 또한 isDone() 메서드를 사용하여 모든 작업이 실행된 후 프로그램이 종료되도록 합니다. 위 프로그램의 출력은 다음과 같습니다.

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

따라서 FutureTask의 이점은 없지만 일부 Future 인터페이스 메서드를 재정의하고 Future 인터페이스의 모든 메서드를 구현하고 싶지 않을 때 유용합니다.