본문 바로가기
Old Posts/Java

[Java] 데몬 스레드(Daemon Thread) 의미와 예제

by A6K 2022. 2. 14.

자바에서 스레드는 일반 스레드와 데몬(Daemon) 스레드로 구분할 수 있다. 일반 스레드는 보통 우리가 아는 스레드의 개념이다. 그렇다면 데몬 스레드는 어떤 스레드이며, 일반 스레드와 어떤 점이 다른지 알아보자.

데몬 스레드(Daemon Thread)

데몬 스레드(Daemon Thread)는 우선 순위가 낮은 스레드로 백그라운드에서 사용자의 애플리케이션을 보조하는 역할을 수행하는 스레드다. 대표적인 데몬 스레드로는 JVM에 생성된 객체들의 메모리 공간을 회수하는 GarbageCollection을 수행하는 스레드가 있다.

데몬 스레드가 일반 스레드와 비교해서 가장 크게 다른 점은 프로그램이 종료할 경우에 발생한다. 사용자의 애플리케이션이 종료될 때, 사용자가 생성한 모든 일반 스레드의 수행이 모두 종료되어야 JVM 프로세스가 종료된다.

하지만 JVM은 데몬 스레드의 종료를 기다리지 않는다. JVM이 종료되는 과정에서 실행중인 데몬 스레드가 있다면 그냥 죽이고 셧다운 작업을 진행한다. 따라서 데몬 스레드는 가장 낮은 우선순위를 갖는 스레드라고 할 수 있다. 이러한 특성 때문에 종료시 특별한 처리가 필요한 작업이라면 데몬 스레드에서 실행해도 되는지 생각해봐야한다.

새로 생성되는 스레드는 항상 부모 스레드의 속성을 상속받는다. 데몬 스레드라는 특성도 마찬가지라서 일반 스레드에서 생성된 스레드는 일반 스레드이고 데몬 스레드에서 생성된 스레드는 데몬 스레드의 특성을 갖는다. JVM이 실행되어 사용자 애플리케이션 로직을 실행하는 메인 스레드는 항상 일반 스레드로 생성된다. 따라서 메인 스레드에서 생성되는 스레드는 기본적으로 일반 스레드로 생성된다.

일반 스레드에서 데몬 스레드를 생성하거나 데몬 스레드에서 일반 스레드를 생성하기 위해서는 'setDaemon(boolean status)' 메소드를 사용해야한다. 이 메소드를 이용해서 생성한 스레드를 데몬 스레드 혹은 일반 스레드로 만들 수 있다.

다만 setDaemon() 메소드는 스레드가 실행되기 전에만 호출할 수 있다. 만약 Thread.start() 메소드 호출 이후에 setDaemon() 메소드가 호출되면 llegalThreadStateException 예외가 발생한다.

현재 스레드가 데몬인지를 확인하기 위해서는 'isDaemon()' 메소드를 이용하면 된다.


데몬 스레드 예제

스레드를 생성하고 데몬 스레드로 만든 후 스레드에서 데몬 스레드 여부를 확인해보자.

public class TestDaemonThread extends Thread{

	public void run(){
		
		// 데몬 스레드인지 확인
		if(Thread.currentThread().isDaemon()){
			System.out.println("Daemon thread");
		}
		else{
			System.out.println("Normal thread executing");
		}
	}
	public static void main(String[] args){

		TestDaemonThread t1=new TestDaemonThread();
		TestDaemonThread t2=new TestDaemonThread();

		//t1을 데몬으로 설정
		t1.setDaemon(true);

		// 스레드 시작 
		t1.start();
		t2.start();
	}
}

t1 스레드만 데몬 스레드로 설정하고 실행해보면

Daemon thread running
Normal thread executing

Process finished with exit code 0

한 스레드에서는 데몬이라고 찍고, 다른 스레드에서는 일반이라고 찍는다.

이 코드를 살짝 고쳐보자.

public class TestDaemonThread extends Thread{

	public void run(){

		// 데몬 스레드인지 확인
		if(Thread.currentThread().isDaemon()){
			while (true) {
				try {
					Thread.sleep(100L);
					System.out.println("Daemon thread running");
				} catch (InterruptedException e) {
					e.printStackTrace();
				}
			}
		}
		else{
			System.out.println("Normal thread executing");
		}
	}
	public static void main(String[] args){

		TestDaemonThread t1=new TestDaemonThread();
		TestDaemonThread t2=new TestDaemonThread();

		//t1을 데몬으로 설정
		t1.setDaemon(true);

		// 스레드 시작
		t1.start();
		t2.start();
	}
}

데몬 스레드인 경우에는 100ms 지연되어 실행되도록 했다.

Normal thread executing

Process finished with exit code 0

데몬 스레드의 실행 결과가 출력되지 않는다. 앞서 언급했던 것처럼 JVM은 데몬 스레드의 종료를 기다려주지 않기 때문이다. 데몬 스레드를 일반 스레드로 실행시키면 두 개의 라인이 출력되는 것을 볼 수 있다.

public class TestIllegalSetDaemon extends Thread {

	public void run(){
		System.out.println("Thread is running");
	}

	public static void main(String[] args){
		TestIllegalSetDaemon t1=new TestIllegalSetDaemon();
		t1.start();

		// 발생 IllegalThreadStateException
		t1.setDaemon(true);
	}
}

스레드가 실행된 이후에 데몬 스레드로 설정하려고 시도하면

Thread is running
Exception in thread "main" java.lang.IllegalThreadStateException
	at java.lang.Thread.setDaemon(Thread.java:1388)
	at thread.TestIllegalSetDaemon.main(TestIllegalSetDaemon.java:14)

Process finished with exit code 1

IllegalThreadStateException이 발생한다.

댓글