Computer >> 컴퓨터 >  >> 프로그래밍 >> Java

Java 스레드 풀(Thread Pool) 개념부터 구현 예제까지


스레드 풀(thread pool)은 미리 생성되어 초기화된 스레드들의 집합입니다. 스레드 풀의 핵심 아이디어는 프로그램이나 서버가 시작될 때 여러 개의 스레드를 미리 만들어 풀(pool)에 넣어두고, 이 스레드들이 작업이 배정되기를 기다리게 하는 것입니다.

서버가 클라이언트의 요청을 받으면, 풀에서 사용 가능한 스레드 하나를 깨워 해당 요청을 처리하도록 전달합니다. 스레드는 서비스 작업을 마치면 폐기되지 않고 다시 풀로 돌아가 다음 작업을 기다립니다. 만약 풀에 사용 가능한 스레드가 없다면, 서버는 스레드가 하나 반환될 때까지 대기하게 됩니다.

스레드 풀의 장점

  • 시간 및 비용 절약: 요청이 올 때마다 새로운 스레드를 생성할 필요가 없으므로 스레드 생성에 드는 오버헤드를 줄일 수 있습니다.
  • 자원 관리: 동시에 실행되는 스레드 수를 제한하여 CPU와 메모리 같은 시스템 자원을 효율적으로 관리할 수 있습니다.
  • 재사용성: 작업을 마친 스레드는 풀로 돌아가 재사용되므로 안정적인 성능을 유지할 수 있습니다.

스레드 풀은 서블릿(Servlet)과 JSP 환경에서도 널리 활용됩니다. 웹 컨테이너(예: Apache Tomcat)는 클라이언트의 요청을 처리하기 위해 내부적으로 스레드 풀을 생성하고 관리합니다.

구현 예제

다음은 Java의 ExecutorServiceExecutors 클래스를 사용하여 스레드 풀을 구현하는 예제입니다.

EmployeeThread.java

import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

class EmployeeThread implements Runnable {
    private String message;

    public EmployeeThread(String s) {
        this.message = s;
    }

    public void run() {
        System.out.println(Thread.currentThread().getName() + " (Start) message = " + message);
        processmessage(); // 스레드를 일정 시간 대기시키는 메서드 호출
        System.out.println(Thread.currentThread().getName() + " (End)");
    }

    private void processmessage() {
        try {
            Thread.sleep(1000); // 1초 대기
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}

ExampleThreadPool.java

public class ExampleThreadPool {
    public static void main(String[] args) {
        ExecutorService executor = Executors.newFixedThreadPool(6); // 6개의 스레드로 구성된 풀 생성
        for (int m = 0; m < 6; m++) {
            Runnable worker = new EmployeeThread("" + m);
            executor.execute(worker); // ExecutorService의 execute 메서드 호출
        }
        executor.shutdown();
        while (!executor.isTerminated()) { } // 모든 작업이 종료될 때까지 대기
        System.out.println("Finished all the threads");
    }
}

주요 클래스 설명

  • ExecutorService: 비동기 작업의 실행을 관리하는 인터페이스로, 스레드 풀의 생명주기를 제어합니다.
  • Executors: 다양한 유형의 스레드 풀을 손쉽게 생성할 수 있는 팩토리 클래스입니다. newFixedThreadPool(int n)은 지정한 크기의 고정 스레드 풀을 생성합니다.
  • shutdown(): 새로운 작업의 접수를 중단하고, 이미 제출된 작업이 모두 완료되면 스레드들을 종료합니다.

실행 결과 예시

pool-1-thread-1 (Start) message = 0
pool-1-thread-2 (Start) message = 1
pool-1-thread-3 (Start) message = 2
pool-1-thread-4 (Start) message = 3
pool-1-thread-5 (Start) message = 4
pool-1-thread-6 (Start) message = 5
pool-1-thread-1 (End)
pool-1-thread-2 (End)
...
Finished all the threads

이처럼 스레드 풀을 사용하면 스레드를 반복해서 생성·소멸시키지 않고도 다수의 작업을 효율적으로 처리할 수 있습니다.