Programming/JAVA
JAVA 스레드 ExecutorService 개요
khj1999
2024. 10. 22. 21:39
Java의 Executor 서비스는 멀티스레딩을 관리하고, 스레드 풀을 생성하여 작업을 실행하는 간편한 방법을 제공. Executor 프레임워크는 스레드를 직접 생성하고 관리하는 대신, 스레드를 재사용할 수 있는 방식으로 효율적인
작업 처리를 가능하게 한다. 이로 인해 코드가 간결해지고, 성능이 향상된다.
1. Executor 프레임워크 개요
Java의 Executor 프레임워크는 다음과 같은 구성 요소로 이루어져 있다:
- Executor 인터페이스: 기본적인 작업 실행 메서드를 정의. (
execute(Runnable command)
) - ExecutorService 인터페이스: Executor의 하위 인터페이스로
종료 및 작업 제출과 같은 추가 기능을 제공. (submit()
,shutdown()
,invokeAll()
, 등) - ThreadPoolExecutor 클래스: ExecutorService의 구현체로, 스레드 풀을 사용하여 작업을 처리
- ScheduledExecutorService 인터페이스: 특정 작업을 지연시키거나 주기적으로 실행할 수 있는 기능을 제공
2. ExecutorService 사용법
ExecutorService를 사용하여 스레드 풀을 생성하고 작업을 제출하는 기본적인 방법은 다음과 같다:
2.1. 스레드 풀 생성
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
public class ExecutorServiceExample {
public static void main(String[] args) {
// 스레드 풀 생성 (2개의 스레드를 가진 고정 스레드 풀)
ExecutorService executorService = Executors.newFixedThreadPool(2);
// 작업 제출
for (int i = 0; i < 5; i++) {
final int taskId = i;
executorService.submit(() -> {
System.out.println("작업 " + taskId + " 실행 중 - 스레드: " + Thread.currentThread().getName());
try {
Thread.sleep(1000); // 작업 수행
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
System.out.println("작업 " + taskId + " 완료");
});
}
// ExecutorService 종료
executorService.shutdown();
}
}
2.2. 작업 제출 및 반환 값 처리
submit()
메서드는 Future
객체를 반환하므로, 작업이 완료된 후 결과를 얻거나 예외를 처리할 수 있다.
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
public class ExecutorServiceWithReturn {
public static void main(String[] args) {
ExecutorService executorService = Executors.newCachedThreadPool();
Future<Integer> future = executorService.submit(new Callable<Integer>() {
@Override
public Integer call() throws Exception {
// 작업 수행
Thread.sleep(1000);
return 42; // 결과 반환
}
});
try {
// 결과를 가져옴
Integer result = future.get();
System.out.println("작업 결과: " + result);
} catch (InterruptedException | ExecutionException e) {
e.printStackTrace();
} finally {
executorService.shutdown();
}
}
}
2.3. ScheduledExecutorService 사용
특정 작업을 지연시키거나 주기적으로 실행하고 싶을 때는 ScheduledExecutorService
를 사용할 수 있다.
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;
public class ScheduledExecutorServiceExample {
public static void main(String[] args) {
ScheduledExecutorService scheduler = Executors.newScheduledThreadPool(1);
// 2초 후에 작업 실행
scheduler.schedule(() -> System.out.println("2초 후에 실행된 작업"), 2, TimeUnit.SECONDS);
// 1초 간격으로 작업 실행
scheduler.scheduleAtFixedRate(() -> System.out.println("주기적으로 실행되는 작업"), 0, 1, TimeUnit.SECONDS);
}
}
3. 장점
- 스레드 관리의 단순화: 스레드 생성과 관리를 Executor 서비스가 처리하므로 코드가 간결해지고
재사용 가능성이 높진다. - 리소스 효율성: 스레드 풀을 사용하여 필요한 수만큼의 스레드를 유지함으로써
불필요한 스레드 생성을 방지한다. - 작업 우선순위 및 시간 관리:
ScheduledExecutorService
를 통해 작업의 우선순위를 관리하고
지연된 실행이나 주기적인 작업 수행이 가능하다.
4. 종료
ExecutorService
를 종료할 때는 shutdown()
또는 shutdownNow()
메서드를 호출:
shutdown()
: 현재 실행 중인 작업이 완료된 후 스레드를 종료.shutdownNow()
: 현재 실행 중인 작업을 중단하고, 대기 중인 작업을 취소.
결론
Java의 Executor 서비스는 멀티스레딩을 쉽게 구현할 수 있게 도와주며, 코드의 가독성과 효율성을 높여준다.
다양한 작업을 효과적으로 처리하기 위해 ExecutorService
및 ScheduledExecutorService
를 활용하면 된다. 이를 통해 안정적이고 관리하기 쉬운 멀티스레딩 프로그램을 작성할 수 있다.