공부하게 된 계기
2023-04-16 자바 게임 프로젝트를 만들고 있던 와중 던전 기능에서 몬스터가 나오게 되면 캐릭터와 몬스터와 싸우는 구조가 된다. 다만, 공격 속도라는 데이터를 가지고 싸우기 때문에 공격속도 만큼 속도에 맞추어서 공격할수 있게 만들고 싶었기 때문에 공부를 하게 되었다. ( Notion 에 정리 했던 글을 좀 더 정리해서 여기다가 써본다. )
동기란?
작업을 하다가 다른 작업을 하게 된다면 다른작업을 끝내고 다시 작업을 시작한다.
비동기란?
작업을 하다가 다른 작업을 하게 된다면 다른 작업도 하면서 작업을 한다.
즉, 아래에 그림으로 정의할수 있을것 같다.
스레드 풀 이란?
스레드 풀(Thread Pool)은 작업 처리를 위해 여러 개의 스레드를 미리 생성해 두고, 작업 큐(Queue)에 들어오는 작업들을 이 스레드들이 처리하는 디자인 패턴입니다. 일반적으로 스레드를 생성하면 삭제하는 비용은 상당히 크다. 이러한 부담을 줄이기 위해서 스레드 풀 이라는 디자인 패턴을 쓰는것이다.
Java 에서는 ThreadPoolExecutor 클래스 를 이용하기도 해서 찾아보고 정리하고 공부해봤다.
ThreadPoolExecutor 클래스의 생성자는 이렇게 정의 되어 있었다.
public ThreadPoolExecutor(
int corePoolSize,
int maximumPoolSize,
long keepAliveTime,
TimeUnit unit,
BlockingQueue<Runnable> workQueue,
ThreadFactory threadFactory,
RejectedExecutionHandler handler
)
여기서 잠깐 찾아본 결과 나도 모르는 클래스들이 있어서 찾아보고 정리해보았다.
일단 먼저 매개변수들을 정의하자면,
corePoolSize : 스레드 풀의 초기 스레드 개수
maximumPoolSize : 스레드 풀의 최대 스레드 개수
keepAliveTime : 코어 스레드 이외의 스레드들이 대기하는 시간
unit : keepAliveTime의 단위
workQueue : 작업 큐
threadFactory : 스레드 생성에 사용되는 팩토리
handler : 작업이 거부될 때 실행할 핸들러
TimeUnit 클래스
자바에서 제공하는 시간 단위를 나타내는 열거형(Enum) 클래스
구현을 한게 된다면 이런 방식으로 사용한다.
TimeUnit.SECONDS.sleep(5); // 5초 동안 대기
아래는 시간단위 이다.
NANOSECONDS : 나노초
MICROSECONDS : 마이크로초
MILLISECONDS : 밀리초
SECONDS : 초
MINUTES : 분
HOURS : 시간
DAYS : 일
BlockingQueue<Runnable> 클래스
BlockingQueue<Runnable> 클래스는 스레드 풀에서 작업을 처리하는데 사용되는 작업 큐이다.
클래스를 구현을 하게 된다면 이런 방식이다.
new ArrayBlockingQueue<Runnable>(2) //생성자에서 큐의 크기를 지정할 수 있습니다. 즉, 큐 2개의 크기
이 클래스의 매서드를 아래에 정리 해놓았다.
add(Runnable r) : 지정된 요소를 큐에 추가합니다. 이 작업이 성공하면 true를 반환하고, 큐가 가득 차서 추가에 실패하면 IllegalStateException 예외를 발생시킵니다.
offer(Runnable r) : 지정된 요소를 큐에 추가합니다. 이 작업이 성공하면 true를 반환하고, 큐가 가득 차서 추가에 실패하면 false를 반환합니다.
put(Runnable r) : 지정된 요소를 큐에 추가합니다. 큐가 가득 차서 요소를 추가할 수 없으면 이 메서드는 스레드를 블록합니다.
take() : 큐에서 요소를 제거하고 반환합니다. 큐가 비어있으면 이 메서드는 스레드를 블록합니다.
poll(long timeout, TimeUnit unit) : 지정된 시간 동안 큐에서 요소를 제거하고 반환합니다. 만약 지정된 시간 동안 큐에서 요소를 가져올 수 없으면 null을 반환합니다.
ThreadFactory 인터페이스
ThreadFactory 객체를 사용하여 스레드를 생성하면, 생성된 스레드의 이름, 우선순위, 그룹 등을 쉽게 지정할 수 있다.
인터페이스 정의는 아래에와 같이 정의 되어있다.
public interface ThreadFactory {
Thread newThread(Runnable r);
}
만약 구현을 하고 싶다면 아래의 예제를 통해 구현을 할수 있다.
public class MyThreadFactory implements ThreadFactory {
private String prefix;
private int count;
public MyThreadFactory(String prefix) {
this.prefix = prefix;
this.count = 1;
}
@Override
public Thread newThread(Runnable r) {
Thread t = new Thread(r, prefix + "-" + count++);
return t;
}
}
ExecutorService 인터페이스
스레드 풀을 추상화한 인터페이스입니다. 구현하는 클래스는 작업을 처리하기 위해 스레드 풀을 생성하고, 작업 처리가 완료되면 스레드 풀에서 스레드를 제거합니다.
아래에 매서드들을 정리 하였다.
submit(Runnable task) : Runnable 객체를 스레드 풀에 제출합니다. 스레드 풀에서 자동으로 스레드를 할당하여 작업을 처리합니다. 작업 처리 결과는 Future 객체로 반환됩니다.
submit(Callable<T> task) : Callable 객체를 스레드 풀에 제출합니다. 스레드 풀에서 자동으로 스레드를 할당하여 작업을 처리합니다. 작업 처리 결과는 Future 객체로 반환됩니다.
invokeAll(Collection<? extends Callable<T>> tasks) : 여러 개의 Callable 객체를 동시에 스레드 풀에 제출합니다. 모든 작업이 완료될 때까지 기다리며, 모든 작업의 결과는 List<Future<T>> 형태로 반환됩니다.
invokeAny(Collection<? extends Callable<T>> tasks) : 여러 개의 Callable 객체를 동시에 스레드 풀에 제출합니다. 가장 먼저 결과를 반환한 작업의 결과만 반환합니다.
shutdown() : 스레드 풀을 종료합니다. 스레드 풀에 등록된 모든 작업이 완료될 때까지 기다리며, 모든 스레드를 제거합니다.
shutdownNow() : 스레드 풀을 강제 종료합니다. 스레드 풀에 등록된 모든 작업을 취소하고, 모든 스레드를 제거합니다.
RejectedExecutionHandler 인터페이스
ExecutorService가 처리할 수 있는 작업의 수를 초과했을 때 발생하는 예외 상황을 처리하기 위한 인터페이스이다.
아래에 매서드를 정리하였다.
rejectedExecution(Runnable r, ThreadPoolExecutor executor) : ExecutorService가 처리할 수 있는 작업의 수를 초과했을 때 호출되는 메서드입니다. 이 메서드에서는 작업을 어떻게 처리할 지를 결정합니다. 예를 들어, 작업을 다시 큐에 넣거나, 예외를 발생시키거나, 다른 작업으로 대체할 수 있습니다.
'TIL' 카테고리의 다른 글
Spring Security AuthenticationProvider / BCryptPasswordEncoder match 에러 (2) | 2023.06.07 |
---|---|
RedisConfig 에서 오류 발생. (0) | 2023.06.01 |
Java_Game 프로젝트 진행중 발생한 문제 공부 ( 멀티스레드 ) (1) | 2023.04.25 |
Java_Game Project / Multi Thread ( 멀티스레드 ) (0) | 2023.04.20 |
개발 블로그 시작... (0) | 2023.04.18 |