ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • 데몬 쓰레드, 쓰레드 우선순위, 쓰레드 그룹
    Java/Java 문법 종합반 강의 정리 2024. 1. 3. 12:46

    데몬 쓰레드 : 보이지 않는 곳(background) 에서 실행되는 낮은 우선순위를 가진 쓰레드를 말한다.
    - 보조적인 역할을 담당하며 대표적인 데몬 쓰레드로는 메모리 영역을 정리해주는 가비지 컬렉터(GC)가 있다.

     

    데몬 쓰레드 사용법

    public class Main {
        public static void main(String[] args) {
            Runnable demon = () -> {
                for (int i = 0; i < 1000000; i++) {
                    System.out.println(i + "번째 demon");
                }
            };
    
            Thread thread = new Thread(demon);
            thread.setDaemon(true); // true로 설정시 데몬스레드로 실행됨
    
            thread.start();
    
            for (int i = 0; i < 100; i++) {
                System.out.println(i + "번째 task");
            }
        }
    }


    사용자 쓰레드


    - 보이는 곳(frontground) 에서 실행되는 높은 우선순위를 가진 쓰레드를 말한다.
    - 프로그램 기능을 담당하며 대표적인 사용자 쓰레드로는 메인 쓰레드가 있다.
    - 기존에 만들었던 쓰레드들이 다 사용자 쓰레드 이다.

    JVM은 사용자 쓰레드의 작업이 끝나면 데몬 쓰레드도 자동으로 종료시켜 버린다.

     

    쓰레드 우선순위와 쓰레드 그룹

    쓰레드 우선순위 : 쓰레드 작업의 중요도에 따라서 쓰레드의 우선순위를 부여할 수 있다.
    - 작업의 중요도가 높을 때 우선순위를 높게 지정하면 더 많은 작업시간을 부여받아 빠르게 처리될 수 있다.
    - 쓰레드는 생성될 때 우선순위가 정해진다.
     - 이 우선순위는 우리가 직접 지정하거나 JVM에 의해 지정될 수 있다.

    우선순위는 아래와 같이 3가지 (최대/최소/보통) 우선순위로 나뉜다.
    - 최대 우선순위 (MAX_PRIORITY) = 10
    - 최소 우선순위 (MIN_PRIORITY) = 1
    - 보통 우선순위 (NROM_PRORITY) = 5
     - 기본 값이 보통 우선순위 이다.
    - 더 자세하게 나눈다면 1 ~ 10 사이의 숫자로 지정 가능하다.
    - 이 우선순위의 범위는 OS가 아니라 JVM에서 설정한 우선순위 이다.

    쓰레드 우선순위는 setPriority() 메서드로 설정할 수 있다.

    Thread thread1 = new Thread(task1);
    thread1.setPriority(8);


    getPriority() 로 우선순위를 반환하여 확인할 수 있다.

    int threadPriority = thread1.getPriority();
    System.out.println("threadPriority = " + threadPriority);

     

    우선순위가 높다고 반드시 쓰레드가 먼저 종료되는 것은 아니라는 것에 주의 하자.

    public class Main {
        public static void main(String[] args) {
            Runnable task1 = () -> {
                for (int i = 0; i < 100; i++) {
                    System.out.print("$");
                }
            };
    
            Runnable task2 = () -> {
                for (int i = 0; i < 100; i++) {
                    System.out.print("*");
                }
            };
    
            Thread thread1 = new Thread(task1);
            thread1.setPriority(8);
            int threadPriority = thread1.getPriority();
            System.out.println("threadPriority = " + threadPriority);
    
            Thread thread2 = new Thread(task2);
            thread2.setPriority(2);
    
            thread1.start();
            thread2.start();
        }
    }

     

    이렇게 예시를 통해 출력을 확인해 봤으나, 예상한 것과는 다르게 생각보다 우선순위의 영향이 크지 않다.

    그것은 위 예시가 너무나 가벼운 작업이기 때문이다.

    만약 무거운 작업을 수행하게 될 때, 쓰레드의 우선순위를 사용하면 확연하게 차이를 느낄 수 있을 것이다.

     

    쓰레드 그룹 : 서로 관련이 있는 쓰레드들을 그룹으로 묶어서 다룰 수 있다.
    - 쓰레드들은 기본적으로 그룹에 포함되어 있다.
     - JVM 이 시작되면 system 그룹이 생성되고 쓰레드들은 기본적으로 system 그룹에 포함된다.
    - 메인 쓰레드는 system 그룹 하위에 있는 main 그룹에 포함된다.
    - 모든 쓰레드들은 반드시 하나의 그룹에 포함되어 있어야 한다.
     - 쓰레드 그룹을 지정받지 못한 쓰레드는 자신을 생성한 부모 쓰레드의 그룹과 우선순위를 상속받게 되는데,
     우리가 생성하는 쓰레드들은 main 쓰레드 하위에 포함된다.
     - 따라서 쓰레드 그룹을 지정하지 않으면 해당 쓰레드는 자동으로 main 그룹에 포함된다.

    쓰레드 그룹 생성
     - ThreadGroup 클래스로 객체를 만들어서 Thread 객체 생성시 첫번째 매개변수로 넣어주면 된다.

    public class Main {
        public static void main(String[] args) {
            Runnable task = () -> {
                while (!Thread.currentThread().isInterrupted()) {
                    try {
                        Thread.sleep(1000);
                        System.out.println(Thread.currentThread().getName());
                    } catch (InterruptedException e) {
                        break;
                    }
                }
                System.out.println(Thread.currentThread().getName() + " Interrupted");
            };
    
            // ThreadGroup 클래스로 객체를 만듭니다.
            ThreadGroup group1 = new ThreadGroup("Group1");
    
            // Thread 객체 생성시 첫번째 매개변수로 넣어줍니다.
            // Thread(ThreadGroup group, Runnable target, String name)
            Thread thread1 = new Thread(group1, task, "Thread 1");
            Thread thread2 = new Thread(group1, task, "Thread 2");
    
            // Thread에 ThreadGroup 이 할당된것을 확인할 수 있습니다.
            System.out.println("Group of thread1 : " + thread1.getThreadGroup().getName());
            System.out.println("Group of thread2 : " + thread2.getThreadGroup().getName());
    
            thread1.start();
            thread2.start();
    
            try {
                // 현재 쓰레드를 지정된 시간동안 멈추게 합니다.
                Thread.sleep(5000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
    
            // interrupt()는 일시정지 상태인 쓰레드를 실행대기 상태로 만듭니다.
            group1.interrupt();
    
        }
    }

     

    총 4초 동안 Thread 2 와 Thread 1 이 1초마다 출력 되며,

    5초가 되는 순간 group1 로 묶인 Thread 1, 2 가 Interrupted(일시정지) 되어 반복문이 종료된다.

    여기서 그룹 쓰레드의 활용성은 하나로 묶을 쓰레드의 개수가 많을 수록 조명된다.

    만약 쓰레드가 100개 였고, 그룹을 쓰지 않는다면 쓰레드 하나하나에 interrupt 를 걸어야 했을 것이다.

     

    다음은 이번 예시에서 사용된 interrupt, sleep 과 같은 쓰레드의 상태와 제어에 대해 알아보자.

    'Java > Java 문법 종합반 강의 정리' 카테고리의 다른 글

    join, yield, synchronized  (4) 2024.01.03
    쓰레드의 상태와 제어  (2) 2024.01.03
    쓰레드 사용법  (1) 2024.01.03
    멀티 쓰레드  (0) 2024.01.03
    프로세스와 쓰레드  (1) 2024.01.03
Designed by Tistory.