[Java][Thread Pool] 쓰레드 풀(Thread Pool) #2 execute()와 submit() 메서드의 차이

2022. 3. 1. 11:58JAVA/Overview

학습목표
1. execute와 submit 메서드의 차이를 학습
2. Java Future 클래스에 대해서 학습

 

1. execute()와 submit() 메서드의 차이는 무엇인가?

쓰레드 풀 객체가 쓰레드를 실행하고자 할때 대표적으로 execute() 메서드와 submit() 메서드를 사용할 수 있습니다. 하지만 대표적인 차이점은 execute() 메서드는 Future 클래스 타입의 객체를 반환하지 않는 것이고 submit() 메서드는 Future 객체를 반환한다는 점입니다.

public class Task implements Runnable{

	@Override
	public void run() {
		System.out.println("call " + Thread.currentThread().getName());
	}

}
public class Driver {
	public static void main(String[] args) throws InterruptedException
	{
		ExecutorService pool = Executors.newFixedThreadPool(5);
		Future<?> f = pool.submit(new Task());
		pool.execute(new Task());
		
		System.out.println(f);
		
		pool.shutdown();
	}
}
call pool-1-thread-1
java.util.concurrent.FutureTask@5b2133b1[Completed normally]
call pool-1-thread-2

위의 결과를 보면 submit() 메서드를 실행후 반환 객체로 Future 클래스 타입의 객체를 반환하는 것을 확인할 수 있습니다.

2. Java Future

Future 클래스는 비동기 계산의 결과를 나타내는 클래스입니다. 비동기 테스크가 생성될때 Future 객체가 반환됩니다. 이 Future 객체의 기능은 비동기 테스크의 결과를 제어합니다. 일단 비동기 계산이 완료되면 테스크가 시작될때 반환된 Future 객체를 통해서 결과 접근이 가능합니다.

 

Java ExecutorService와 같은 Java의 기본 동시성 유틸리티(Java's built-in concurrency utilities)는 일부 메소드(submit 등)에서 Java Future 객체를 반환합니다. ExuecutorService의 경우 동시에(비동기적으로) 실행할 Callable 또는 Runnable 타입의 객체를 제출하면 Future 객체를 반환받을 것입니다.

 

Java Future Interface 정의

public interface Future<V> {
    boolean cancel(boolean mayInterruptIfRunning)
    V       get();
    V       get(long timeout, TimeUnit unit);
    boolean isCancelled();
    boolean isDone();
}

 

Future 객체로부터 결과 얻기

위와 같이 Java Future 클래스는 비동기 테스크의 결과를 나타냅니다. 결과를 얻기 위해서 get() 메서드를 호출할 수 있습니다.

Future future = ... // get Future by starting async task

// do something else, until ready to check result via Future

// get result from Future
try {
    Object result = future.get();
} catch (InterruptedException e) {
    e.printStackTrace();
} catch (ExecutionException e) {
    e.printStackTrace();
}

만약 비동기 테스크와 완료되기 전에 get() 메서드가 호출된다면 get 메서드는 결과가 준비될때까지 대기한 다음 호출될 것입니다.

 

get() 메서드는 인자를 설정할 수 있습니다. 첫번째 매개변수는 시간값이고 두번째 매개변수는 시간단위(밀리초, 초)입니다. 아래의 예제는 최대 대기할 시간을 1000밀리초로 설정한 예제입니다. 만약 1000밀리초 후에도 결과가 없다면 TimeoutException이 호출됩니다.

try {
    Object result =
        future.get(1000, TimeUnit.MILLISECONDS);
} catch (InterruptedException e) {

} catch (ExecutionException e) {

} catch (TimeoutException e) {
    // thrown if timeout time interval passes
    // before a result is available.
}

 

Future cancel() 메서드를 통한 테스크 취소

Future 객체가 cancel 메서드를 호출하여 진행중인 비동기 테스크를 취소할 수 있습니다.

f.cancel(false);

 

테스크가 완료되었는지 검사 (isDone)

비동기 계산이 완료되었는지 검사하는 메서드입니다. 

Future future = ... // Get Future from somewhere

if(future.isDone()) {
    Object result = future.get();
} else {
    // do something else
}

 

테스크가 취소되었는지 검사 (isCancelled)

비동기 계산이 취소되었는지 검사하는 메서드입니다.

Future future = ... // get Future from somewhere

if(future.isCancelled()) {

} else {

}

 

References

https://stackoverflow.com/questions/4016091/what-is-the-difference-between-submit-and-execute-method-with-threadpoolexecutor
http://tutorials.jenkov.com/java-util-concurrent/java-future.html#:~:text=Future%20%2C%20represents%20the%20result%20of,result%20of%20the%20asynchronous%20task.