[JAVA] Daemon Thread와 Thread pool
데몬 스레드
백그라운드에서 실행되는 보조 스레드로, 주 스레드의 작업을 돕는 보조역할을 하는 스레드이다.
주 스레드가 종료되면 데몬 스레드도 따라서 같이 종료된다.
ex: 가비지 컬렉터, 유튜브에서 음악을 재생하고 있다가 유튜브 종료하면 음악도 종료
데몬 스래드 생성
public static void main(String[] args){
TestDaemonThread thread = new TestDaemonThread(); //스레드 객체 생성
thread.setDaemon(true); //데몬스레드로 지정
thread.start();
}
스레드풀
작업 처리에 사용되는 스레드를 미리 지정된 갯수만큼 정해서 들어오는 작업들을 스레드가 하나씩 맡아 처리하는 방식이다.
스레드의 갯수가 많아지면 비용이 증가한다. 스레드 생성에 시간과 메모리 비용이 늘어난다.
그렇기에 미리 스레드를 만들어놓고
반복적인 병렬작업을 하면서 어떠한 스레드가 작업을 마치면 그 스레드를 재활용하는 방식으로 간다면 효율적이다.
그러면 적은 수의 스레드를 만들면서 효율적인 처리가 가능하다.
* 반복적인 100번의 작업에서 일일이 스레드를 생성한다면 100번을 만들어야 하는데 이것은 낭비이다.
즉 노는 스레드가 없게 타이트하고 효율적이게 재활용한다.
스레드풀의 생성
Executors 클래스를 이용하면 된다. 이 클래스의 정의된 정적 메서드를 이용하면 인터페이스인 ExecutorService의 구현체를 만들 수 있다.
| 메서드명 | 초기수 | 코어수 | 최대수 |
| newCachedThreadPool | 0 | 0 | Integer_MAX_VALUE |
| newFixedThreadPool | 0 | 생성된 수 | nThreads |
초기수: 스레드풀 생성시 생기는 스레드의 초기 갯수
코어수: 사용되지 않는 스레드를 제거할때 풀에 남겨놓고 유지할 스레드 수
최대수: 최대로 가질 수 있는 스레드 수
ExecutorService executorService = Executors.newCacheThreadPool();
ExecutorService executorService = Executors.newFixedThreadPool(10);
//직접 커스텀하여서 생성
ExecutorService executorService = new ThreadPoolExecutor(
5, //코어 스레드 수
100, //최대 스레드 수
120L, //작업 완료후 대기 시간
TimeUnit.SECONDS, //작업 완료후 대기시간 단위
new SynchronousQueue<Runnable>() //동기화된 큐 (작업 큐) 한번에 하나씩만 작업 큐에 스레드를 넣을 수 있도록 동기화사용
);
스레드풀의 종료
이것들도 멀티 스레드이기때문에 메인 스레드가 종료되어도 계속 실행된다.
작업의 종료에는 다음과 같은 메서드가 사용된다.
| 리턴타입 | 메서드 | 설명 |
| void | shutdown | 처리 중인 작업과 작업큐에 있는 모든 작업을 처리한뒤에 스레드풀 종료 |
| List<Runnable> | shutdownNow | 처리 중인 작업과 작업큐에 있는 모든 작업을 중지시킨다. 작업큐에 있던 미처리 목록을 리턴한다. |
하나의 작업은 Callable 혹은 Runnable로 구현클래스를 표현한다.
만약 스레드에서 처리해야하는 작업이 리턴값이 있다면 Callable<T> 를 리턴하고 없다면 Runnable을 리턴한다.
작업 처리 요청
작업의 처리를 위해 스레드를 작업큐에 넣기 위해 요청을 하는것이다. 작업큐에 넣으면 알아서 작업을 처리할 것이다.
아래에 메서드를 통해 요청을 할 수 있다.
| 리턴타입 | 메서드명 | 설명 |
| void | execute | Runnable 객체를 작업큐에 저장 |
| Future<T> | submit() | Callable 객체를 작업큐에 저장 |