Runnable, Callable

namkun·2023년 9월 4일
0

T-I-L

목록 보기
20/20

Runnable과 Callable 모두 멀티스레드에서 작업을 수행할 수 있게 설계되어있습니다.

Runnable 작업들은 Thread 클래스 또는 ExecutorService 에서 실행할 수 있으나, Callable은 오직 ExecutorService 에서 만 실행할 수 있습니다.

Runnable

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

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에 대해서 알아보았습니다.

상황에 맞게 잘 사용하면 될 것 같습니다.

profile
개발하는 중국학과 사람

0개의 댓글