자바에서 Executor와 ExecutorService는 자바의 동시성(concurrency) 프로그래밍을 위한 핵심 인터페이스입니다. 이들은 작업 실행을 추상화하여 개발자가 스레드 관리의 복잡성으로부터 벗어날 수 있게 돕습니다. 아래에서 각각에 대해 자세히 설명하겠습니다.
Executor
Executor 인터페이스는 java.util.concurrent 패키지에 속해 있으며, 단일 추상 메소드 execute(Runnable command)를 가지고 있습니다. 이 메소드는 주어진 작업(Runnable 객체)을 실행하는 방법을 정의합니다. Executor를 구현하는 클래스는 이 execute 메소드를 통해 어떻게 그리고 언제 작업을 실행할지 결정합니다. 이 인터페이스는 작업의 실행을 간단하게 추상화하여, 실행 메커니즘(예: 스레드 사용 방법)을 사용자로부터 숨깁니다.
Executor executor = anExecutor;
executor.execute(new Runnable() {
public void run() {
// 작업 내용
}
});
Executor 인터페이스는 개발자들이 해당 작업의 실행과 쓰레드의 사용 및 스케줄링 등으로부터 벗어날 수 있도록 도와준다. 단순히 전달받은 Runnable 작업을 사용하는 코드를 Executor로 구현하면 다음과 같다
@Test
void executorRun() {
final Runnable runnable = () -> System.out.println("Thread: " + Thread.currentThread().getName());
Executor executor = new RunExecutor();
executor.execute(runnable);
}
static class RunExecutor implements Executor {
@Override
public void execute(final Runnable command) {
command.run();
}
}
출처: https://mangkyu.tistory.com/259 [MangKyu's Diary:티스토리]
ExecutorService
ExecutorService는 Executor를 확장한 더 복잡한 인터페이스로, 생명주기 관리(lifecycle management)와 작업 실행 결과를 추적할 수 있는 기능을 제공합니다. ExecutorService를 사용하면, 비동기 작업을 제출하고, 작업이 완료될 때까지 기다리며, 작업 실행을 취소하고, 실행자 서비스를 종료할 수 있습니다. ExecutorService에는 작업을 제출하기 위한 다양한 submit 메소드가 있으며, 이들은 Future 객체를 반환하여 나중에 작업의 결과를 검색할 수 있게 합니다.
ExecutorService는 주로 다음과 같은 메소드들을 제공합니다:
- shutdown(): 실행자 서비스를 순차적으로 종료시키며, 이미 제출된 작업은 실행되지만 새 작업은 받지 않습니다.
- shutdownNow(): 실행자 서비스를 즉시 종료시키며, 대기 중인 작업은 실행되지 않습니다.
- submit(Callable<T> task): 값을 반환할 수 있는 작업을 제출하고, 작업이 완료될 때 결과를 받을 수 있는 Future<T>를 반환합니다.
- invokeAll(...): 작업 컬렉션을 실행하고, 모든 작업이 완료될 때까지 기다린 후, 결과를 반환합니다.
ExecutorService 인터페이스에서 제공하는 주요 메소드들과 각각의 사용 예제를 아래에 설명하겠습니다. 이 인터페이스는 다양한 방법으로 작업을 실행하고, 관리하는 기능을 제공합니다
1. execute(Runnable command)
단순한 Runnable 작업을 실행합니다. 작업의 결과를 반환받을 수는 없습니다.
ExecutorService executorService = Executors.newSingleThreadExecutor();
executorService.execute(new Runnable() {
public void run() {
System.out.println("Asynchronous task");
}
});
executorService.shutdown();
2. submit(Runnable task)
Runnable 작업을 실행하고, 작업이 완료될 때까지 기다리는 데 사용할 수 있는 Future<?>를 반환합니다.
ExecutorService executorService = Executors.newSingleThreadExecutor();
Future<?> future = executorService.submit(new Runnable() {
public void run() {
System.out.println("Asynchronous task");
}
});
executorService.shutdown();
3. submit(Callable<T> task)
Callable 작업을 실행하고, 작업의 결과를 받을 수 있는 Future<T>를 반환합니다.
ExecutorService executorService = Executors.newSingleThreadExecutor();
Future<String> future = executorService.submit(new Callable<String>() {
public String call() {
return "Result of the asynchronous computation";
}
});
executorService.shutdown();
4. invokeAll(Collection<? extends Callable<T>> tasks)
주어진 작업들의 컬렉션을 실행하고, 모든 작업이 완료될 때까지 기다린 다음, 각 작업의 결과를 담은 List<Future<T>>를 반환합니다.
ExecutorService executorService = Executors.newSingleThreadExecutor();
List<Callable<String>> callables = Arrays.asList(
() -> "Task 1",
() -> "Task 2",
() -> "Task 3"
);
try {
List<Future<String>> futures = executorService.invokeAll(callables);
for(Future<String> future : futures){
System.out.println(future.get());
}
} catch (InterruptedException | ExecutionException e) {
e.printStackTrace();
}
executorService.shutdown();
5. invokeAny(Collection<? extends Callable<T>> tasks)
주어진 작업들의 컬렉션 중 하나를 실행하고, 가장 먼저 완료되는 작업의 결과를 반환합니다. 나머지 작업은 취소됩니다.
ExecutorService executorService = Executors.newSingleThreadExecutor();
List<Callable<String>> callables = Arrays.asList(
() -> {
TimeUnit.SECONDS.sleep(2);
return "Task 1";
},
() -> {
TimeUnit.SECONDS.sleep(1);
return "Task 2";
},
() -> {
TimeUnit.SECONDS.sleep(3);
return "Task 3";
}
);
String result = executorService.invokeAny(callables);
System.out.println(result); // "Task 2" 의 결과가 가장 빨리 나올 것입니다.
executorService.shutdown();
Executor와 ExecutorService는 자바에서 동시성을 다룰 때 중요한 구성 요소입니다. 이들을 사용함으로써 스레드를 직접 관리하는 복잡성을 줄이고, 효율적이고 안정적인 동시 실행을 구현할 수 있습니다.
6. shutdown()
실행자 서비스를 순차적으로 종료합니다. 이미 제출된 작업은 완료되지만, 새 작업은 받지 않습니다.
ExecutorService executorService = Executors.newSingleThreadExecutor();
// 작업 제출 등
executorService.shutdown();
7. shutdownNow()
실행자 서비스를 즉시 종료하고, 현재 대기 중이거나 실행 중인 작업 목록을 반환합니다.
ExecutorService executorService = Executors.newSingleThreadExecutor();
// 작업 제출 등
List<Runnable> notExecutedTasks = executorService.shutdownNow();
참고 : https://mangkyu.tistory.com/259
'프로그래밍언어 > JAVA' 카테고리의 다른 글
getDeclaredConstructor().newInstance()? (0) | 2024.03.16 |
---|---|
Reflection API란? (0) | 2024.03.16 |
<JAVA>멀티스래드 프로그래밍-3 (0) | 2020.12.13 |
<JAVA>멀티 스레드 프로그래밍 -2 (0) | 2020.12.13 |
<JAVA>멀티스래드 프로그래밍-1 (0) | 2020.12.13 |