Runnable과 Callable 모두 멀티스레드에서 작업을 수행할 수 있게 설계되어있습니다.
Runnable 작업들은 Thread 클래스 또는 ExecutorService 에서 실행할 수 있으나, Callable은 오직 ExecutorService 에서 만 실행할 수 있습니다.
Runnable은 멀티스레드 작업을 표현하기 위해서 자바에서 제공하는 인터페이스 입니다.
@FunctionalInterface
public interface Runnable {
/**
* When an object implementing interface <code>Runnable</code> is used
* to create a thread, starting the thread causes the object's
* <code>run</code> method to be called in that separately executing
* thread.
* <p>
* The general contract of the method <code>run</code> is that it may
* take any action whatsoever.
*
* @see java.lang.Thread#run()
*/
public abstract void run();
}
오직 run()
메서드만 갖고 있고, 어떠한 파라미터도 없으며 어떠한 값도 반환받지 않습니다.
그렇기에 스레드의 결과값이 필요하지 않을때 사용합니다.
예를 들면 아래처럼요.
thread class
@Slf4j
public class EventLoggingTask implements Runnable {
@Override
public void run(){
log.info("MSG");
}
}
run method
public void executeTask(){
ExecutorService executorService = Executors.newFixedThreadPool(2);
executorService.execute(new Thread(EventLoggingTask::new));
executorService.shutdown();
}
위 경우는 단순하게 스레드 내부의 run이 실행될 뿐입니다.
Callable 인터페이스는 generic 값인 V를 반환하는 call()
메서드만 포함하는 인터페이스입니다.
@FunctionalInterface
public interface Callable<V> {
/**
* Computes a result, or throws an exception if unable to do so.
*
* @return computed result
* @throws Exception if unable to compute a result
*/
V call() throws Exception;
}
위의 Runnable과 다른점이라면 결과값을 계산할 수 없는 경우 Exception을 던진다는 점입니다.
아래의 예시를 통해 이해해봅시다.
thread class
public class FactorialTask implements Callable<Integer> {
int number;
public FactorialTask(int number) {
this.number = number;
}
@Override
public Integer call() throws Exception {
int fact = 1;
for(int count = number; count > 1; count--) {
fact = fact * count;
}
return fact;
}
}
위처럼 스레드 클래스에서 Integer 값을 반환할 수 있게 해두었습니다.
call Method
public void whenTaskSubmitted_ThenFutureResultObtained() throws ExecutionException, InterruptedException {
ExecutorService executorService = Executors.newSingleThreadExecutor();
FactorialTask task = new FactorialTask(5);
Future<Integer> future = executorService.submit(task);
Integer result = future.get();
System.out.println(result);
}
위처럼 사용하면, submit 함과 동시에 스레드 내부의 call 이 실행됩니다.
그리고 이를 Future class를 통해 반환 받은 뒤, get()
메서드를 이용해서 가져올 수 있게 됩니다.
Runnable과 Callable에 대해서 알아보았습니다.
상황에 맞게 잘 사용하면 될 것 같습니다.
Really unquie place, Thank you so much meant for posting The experience. Fantasticly penned report, anxieties most of folks given similar volume of material as you may, the online market place might be a a lot better put. Be sure to keep it up! thca flower in arizona