스레드 풀(1)

2022. 5. 7. 17:28java/java

*스레드 폭증

 1) 병렬 작업 처리가 많아지면 스레드의 개수가 증가

 2) 스레드 생성과 스케쥴링으로 인해 CPU가 바빠지고, 메모리 사용량이 늘어난다.

 3) 따라서 애플리케이션의 성능이 급격히 저하된다.

 

*스레드 풀

 1) 작업 처리에 사용되는 스레드를 제한된 개수만큼 미리 생성

 2) 작업 큐에 들어오는 작업들을 하나씩 스레드가 맡아 처리

 3) 작업 처리가 끝난 스레드는 작업 결과를 애플리케이션으로 전달.

 4) 스레드는 다시 작업큐에서 새로운 작업을 가져와 처리

 

*ExecutorService 인터페이스와 Excutors 클래스

 1) 스레드풀을 생성하고 사용할 수 있도록 java.util.concurrent패키지에서 제공

 2) Excutors의 정적 메소드를 이용해서 ExcutorService 구현 객체 생성

 3) 스레드 풀 = ExecutorService 객체

 

*ExecutorService 동작 원리

 

*스레드풀 생성

1) 다음 두가지 메소드 중 하나로 간편 생성

  - newCachedThreadPool()

    -1) int 값이 가질 수 있는 최대 값만큼 스레드가 추가되나, 운영체제의 상황에 따라 달라진다.

    -2) 1개 이상의 스레드가 추가되었을 경우

    -3) 60초 동안 추가된 스레드가 아무 작업을 하지 않으면

    -4) 추가된 스레드를 종료하고 풀에서 제거한다.

ExecutorService executorService = Excutor.newCachedThreadPool();

 

  -newFixedThreadPool(int nThreads)

    -1) 코어 스레드 개수와 최대 개수가 매개값으로 준 nThread이다

    -2) 스레드가 작업을 처리하지 않고 놀고 있더라도 스레드 개수가 줄 지 않는다.

ExcutorService excutorService = Excutors.newFixedThreadPool(
	Runtime.getRuntime().availableProcessors(); //현재 cpu의 코어의 수
)

 

 2) ThreadPoolExecutor을 이용한 직접 생성

  - newCachedThreadPool()와 newFixedThreadPool(int n Threads)가 내부적으로 생성

  - 스레드의 수를 자동으로 관리하고 싶을 경우 직접 생성해서 사용

 

 Ex)

  - 코어 스레드 개수가 3, 최대 스레드 개수가 100인 스레드 풀을 생성

  - 3개를 제외한 나머지 추가된 스레드가 120초 동안 놀고 있을 경우

  - 해당 스레드를 제거해서 스레드 수를 관리

 

ExecutorService threadPool = new ThreadPoolExecutor(
    3, 		//코어 스레드 개수
    100,	//최대 스레드 개수
    120L,	//놀고 있는 시간
    TimeUnitSECONDS,	//놀고 있는 시간 단위
    new SynchronousQueue<Runnable>()	//작업큐
);

 

*스레드풀 종료

1) 스레드풀의 스레드는 기본적으로 데몬 스레드가 아니다.

 - main스레드가 종료되더라도 스레드풀의 스레드는 작업을 처리하기 위해 계속 실행되므로

   애플리케이션은 종료되지 않는다.

   따라서 스레드풀을 종료해서 모든 스레드를 종료시켜야 한다.

 

2) 스레드풀 종료 메서드

리턴타입 메소드명(매개변수) 설명
void shutdown() 현재 처리 중인 작업뿐만 아니라 작업큐에 대기하고 있는 모든 작업을 처리한 뒤에 스레드풀을 종료시킨다.
List<Runnable> shutdownNow() 현재 작업 처리 중인 스레드를 interrupt 해서 작업 중지를 시도하고 스레드 풀을 종료시킨다. 리턴값은 작업큐에 있는 미처리된 작업(Runnable)의 목록이다.
boolean awaitTermination(
  long timeout,
  TimeUnit unit)
shutdown() 메소드 호출 이후, 모든 작업 처리를 timeout 시간 내에 완료하면 true를 리턴하고, 완료하지 못하면 작업 처리 중인 스레드를 interrupt 하고 false를 리턴한다.

 

*작업 생성

 1) 하나의 작업은 Runnable 또는 Callable 객체로 표현한다.

 2) Runnable과 Callable의 차이점

  -작업 처리 환료 후 리턴값이 있느냐 없느냐이다.

 

 

 3) 스레드풀에서 작업 처리

  - 작업 큐에서 Runnable또는 Callable 객체를 가져와

  - 스레드로 하여금 run()과 call() 메소드를 실행토록 하는 것이다.

 

*작업 처리 요청

 1) ExecutorService의 작업 큐에 Runnable 또는 Callable 객체를 넣는 행위를 말한다.

 2) 작업 처리 요청을 위해 ExecutorService는 다음 두 가지 종류의 메소드를 제공한다.

 

 3) 작업 처리 도중 예외가 발생할 경우

  execute(): 스레드가 종료되고 해당 스레드는 제거된다. 따라서 스레드풀은 다른 작업 처리를 위해 재사용된다.

  submit():  스레드가 종료되지 않고 다음 작업을 위해 재사용된다.

'java > java' 카테고리의 다른 글

어노테이션  (2) 2023.11.26
UDP 네트워킹  (0) 2022.06.04
TCP 네트워킹  (0) 2022.05.07
TCP 네트워킹  (0) 2022.05.07
보조 스트림(2)  (0) 2022.05.01