item80
작업 큐를 손수 만드는 일은 삼가야 하고, 스레드를 직접 다루는 것도 일반적으로 삼가야 한다. 스레드를 직접 다루면 Thread가 작업 단위와 수행 매커니즘 역할을 모두 수행하게 된다. 반면 실행자 프레임워크에서는 작업 단위와 실행 매커니즘이 분리된다.
new Thread(new RunnableTask()).start();
와 같은 방식으로 스레드를 생성하고 실행하는 것을 의미한다.실행자 프레임워크를 사용하면, 작업 단위를 별도의 실행 메커니즘에 전달하여 비동기적으로 실행할 수 있다. 이는 개발자가 직접 스레드를 관리하지 않고도 작업을 효율적으로 처리할 수 있게 해준다.
주요 클래스 및 인터페이스
package com.example.executor;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;
public class ExecutorServiceExample {
public static void main(String[] args) {
// 스레드 풀 생성 (고정된 크기: 5개의 스레드)
ExecutorService executorService = Executors.newFixedThreadPool(5);
// 10개의 작업 제출
for (int i = 1; i <= 10; i++) {
Task task = new Task(i);
executorService.submit(task);
}
// ExecutorService 종료 요청
executorService.shutdown();
try {
// 모든 작업이 완료될 때까지 대기
if (!executorService.awaitTermination(60, TimeUnit.SECONDS)) {
executorService.shutdownNow(); // 아직 실행 중인 작업을 강제 종료
if (!executorService.awaitTermination(60, TimeUnit.SECONDS)) {
System.err.println("ExecutorService did not terminate");
}
}
} catch (InterruptedException e) {
executorService.shutdownNow();
Thread.currentThread().interrupt();
}
System.out.println("All tasks completed.");
}
static class Task implements Runnable {
private final int taskId;
public Task(int taskId) {
this.taskId = taskId;
}
@Override
public void run() {
System.out.println("Task ID: " + this.taskId + " performed by " + Thread.currentThread().getName());
try {
// 작업 시뮬레이션을 위한 대기
Thread.sleep(1000);
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
System.out.println("Task ID: " + this.taskId + " was interrupted");
}
}
}
}