## 44. 스레드 재사용하기 : 스레드풀(thread pool) 구현
- Pooling 기법을 활용하여 스레드를 재사용하는 방법
- GoF의 FlyWeight 디자인 패턴(풀링 기법)을 적용하여 스레드풀을 구현하는 방법
ㄴ report-server 의 bitcamp.util 패키지에 TreadPool 이라는 이름의 클래스를 생성
ㄴ report-server 의 bitcamp.util 패키지에 ResourcePool 이라는 이름의 interface 를 생성
ResourcePool.java
ㄴ report-server 의 bitcamp.util 패키지에 ManagedThread 라는 이름의 클래스를 생성
ManagedThread.java
ㄴ ManagedThread 클래스는 Thread 를 상속 받도록 함
ThreadPool.java
ㄴ ThreadPool 클래스는 bitcamp.util 패키지에 있는 ResourcePool<ManagedThread>을 구현함
ㄴ ThreadPool 클래스는 ManagedThread 객체의 리스트를 유지함
ThreadPool.java
ㄴ getResource() 메서드를 오버라이딩 함
ThreadPool.java
ㄴ returnResource 메서드를 오버라이딩 함
ThreadPool.java
ㄴ getResource 메서드는 리스트가 비어있으면 새로운 ManagedThread 객체를 생성하여 반환하고, 그렇지 않은 경우 리스트에서 첫 번째 ManagedThread 객체를 제거하고 반환함
ㄴ returnResource 메서드는 전달된 ManagedThread 객체를 리스트에 추가함
ManagedThread.java
ㄴ ResourcePool<ManagedThread>을 가리키는 pool 멤버 변수를 가지고 있음
ㄴ ManagedThread 클래스는 Thread를 확장하여 스레드 동작을 수행할 수 있음
ㄴ 생성자에서는 ResourcePool<ManagedThread>을 인자로 받아 pool 멤버 변수에 할당함
=> 이를 통해 ManagedThread가 속한 스레드 풀을 알 수 있음
ㄴ report-server 의 bitcamp.util 패키지에 Job 이라는 이름의 interface 를 생성
Job.java
ㄴ execute 메서드를 규칙으로 정의
ㄴ Job 인터페이스는 execute()라는 하나의 메서드를 선언함
ㄴ 이 메서드는 작업의 실행 로직을 나타내며 매개변수를 받지 않고 반환값이 없음
ㄴ Job 인터페이스는 다른 클래스가 구현하여 특정 작업을 정의하는 데 사용됨
ㄴ Job 인터페이스를 구현함으로써 클래스는 execute() 메서드에 대한 자체 구현을 제공할 수 있으며, 이는 작업이 실행되어야 할 때 호출됨
ManagedThread.java
=>
ㄴ setJob 메서드는 Job 객체를 받아서 job 멤버 변수에 할당하고, notify를 호출하여 스레드를 깨우도록 함
ㄴ run 메서드에서는 무한 루프를 실행하며, 스레드가 대기 상태로 들어갈 때마다 wait를 호출하여 대기하도록 함
ㄴ job 객체가 할당된 경우 해당 작업을 실행한 후, job을 초기화하고 스레드를 리소스 풀에 반환하도록 함
ThreadPool.java
ㄴ 새 스레드 생성될 경우 "새 스레드 생성!" 을 출력하도록 하여 확인
ThreadPool.java
ㄴ 기존 스레드가 리턴될 경우 " 기존 스레드 리턴!" 을 출력하도록 하여 확인
ServerApp.java
ㄴ 스레드를 리턴해줄 스레드풀 준비
ServerApp.java
ㄴ 클래스 이름을 RequestAgentThread => RequestProcessJob 으로 변경
ㄴ Job 인터페이스를 구현하도록 함
ㄴ run => execute 로 변경
ServerApp.java
ㄴ threadPool.getResource()를 호출하여 스레드 풀에게 스레드 자원을 요청함
ㄴ getResource() 메서드는 스레드 풀에서 사용 가능한 스레드를 가져오는 역할을 함
ㄴ getResource() 메서드로부터 반환된 ManagedThread 객체를 t 변수에 할당합니다.
ㄴ t.start()를 호출하여 ManagedThread 객체를 시작함
ㄴ start() 메서드는 해당 스레드의 run() 메서드를 실행하게 됨
ThreadPool.java
ㄴ getResource() 메서드는 스레드 풀에서 사용 가능한 스레드를 가져옴
ㄴ 스레드 풀의 리스트가 비어있는 경우, 새로운 ManagedThread 객체를 생성하고, start() 메서드를 호출하여 스레드를 시작하고 생성된 스레드를 반환함
ㄴ 스레드 풀의 리스트에 스레드가 있는 경우, 리스트에서 첫 번째 스레드를 제거하고 반환함
ㄴ returnResource() 메서드는 사용한 스레드를 스레드 풀에 반환하고 리스트에 스레드를 추가함
ㄴ 스레드 생성, 시작, 반환 등의 동작을 확인하기위해 각각 동작마다 내용 출력
ServerApp.java
ㄴ serverSocket.accept()를 호출하여 클라이언트의 소켓 연결을 기다고, 클라이언트가 연결되면 해당 클라이언트 소켓을 socket 변수에 할당함
ㄴ threadPool.getResource()를 호출하여 스레드 풀에게 스레드 자원을 요청하도록 함
ㄴ getResource() 메서드로부터 반환된 ManagedThread 객체를 t 변수에 할당함
ㄴ t.setJob(new RequestProcessJob(socket))을 호출하여 ManagedThread 객체에 클라이언트 소켓을 처리할 작업(RequestProcessJob)을 할당함
=> 클라이언트의 소켓 연결이 수신되면 해당 소켓을 처리할 스레드를 스레드 풀에서 가져온 후 작업을 할당함
server 실행하여 확인
=>
서버
클라이언트
ManagedThread.java
ㄴ 스레드 번호를 추적하기 위한 추가적인 정적 변수 count와 각 스레드의 고유 식별자를 저장하는 인스턴스 변수 no 를 선언함
ManagedThread.java
ㄴ ManagedThread 객체가 생성될 때마다 no 를 1씩 증가시킴(count 변수 이용)
ManagedThread.java
ㄴ 스레드가 start 될 때마다 몇 번 스레드가 실행되는지 확인하기 위해 해당 코드 추가
ThreadPool.java
ㄴ 생성한 스레드가 바로 실행될 수 있도록 main 스레드가 잠시 잠들도록 해줌
익명 클래스로 만든 후 람다로 변경하기
ServerApp.java
=>
ServerApp.java
=>
ServerApp.java
=>
ServerApp.java
=>
ServerApp.java
=>
ServerApp.java
=>
ServerApp.java
=>
ServerApp.java
=>
ServerApp.java
'네이버클라우드 > JAVA 웹 프로그래밍' 카테고리의 다른 글
JAVA 39일차 (2023-07-17) 자바 프로그래밍_45. 스레드 풀_개인프로젝트 - 마트 관리 시스템 (0) | 2023.07.17 |
---|---|
JAVA 39일차 (2023-07-17) 자바 프로그래밍_스레드 풀 사용법 (0) | 2023.07.17 |
JAVA 38일차 (2023-07-14) 자바 프로그래밍_스레드, 임계영역(Critical Region, Critical Section) (0) | 2023.07.14 |
JAVA 37일차 (2023-07-13) 자바 프로그래밍_스레드와 멀티태스킹 (0) | 2023.07.13 |
JAVA 36일차 (2023-07-12) 자바 프로그래밍_여러 클라이언트 요청을 동시에 처리하기: Thread 적용_개인프로젝트 - 마트 관리 시스템 (0) | 2023.07.12 |