TIL

  • thread
    1. main 스레드
    2. 싱글스레드와 멀티스레드
    3. I/O blocking
    4. 스레드 우선순위
    5. 스레드 그룹

 


 

1. main 스레드

  • main() 메소드의 코드를 수행하는 스레드
  • 스레드는 사용자 스레드데몬 스레드 두 종류가 있다.
    • main 스레드는 사용자 스레드이다.
    • 데몬 스레드는 <사용자 스레드의 보조 역할>을 하는 스레드이다.
    • 실행 중인 사용자 스레드가 하나도 없을 때, 프로그램은 종료된다.
    • main 스레드가 종료돼도 실행 중인 스레드가 있으면 프로그램은 종료되지 않는다.

 

public class Main {
    public static void main(String[] args) {
        Thread1 th1 = new Thread1();
        Thread2 th2 = new Thread2();

        th1.start();
        th2.start();

        System.out.println("==== main method 종료 ====");
    }
}

class Thread1 extends Thread {
    public void run() { // 스레드가 수행할 작업
        for (int i = 0; i < 300; i++) {
            System.out.print(0);
        }
    }
}

class Thread2 extends Thread {
    public void run() { // 스레드가 수행할 작업
        for (int i = 0; i < 300; i++) {
            System.out.print(1);
        }
    }
}

 

  • main 스레드가 먼저 종료되고 th1 스레드, th2 스레드 그리고 마지막으로 프로그램이 종료된다.

 

 

public class Main {
    public static void main(String[] args) {
        Thread1 th1 = new Thread1();
        Thread2 th2 = new Thread2();

        th1.start();
        th2.start();

        try {
            // main 스레드가 th1, th2 스레드의 작업이 끝날 때까지 기다린다.
            th1.join();
            th2.join();
        } catch (InterruptedException e) {
            throw new RuntimeException(e);
        }

        System.out.println("==== main method 종료 ====");
    }
}

 

  • main 스레드가 마지막에 종료되고, 최종적으로 프로그램이 종료된다.

 

 

 

 

2. 싱글스레드와 멀티스레드

 

싱글스레드

public class Main {
    public static void main(String[] args) {

        for (int i = 0; i < 300; i++) {
            System.out.println("-");
        }

        for (int i = 0; i < 300; i++) {
            System.out.println("|");
        }
    }
}

  • 첫번째 반복문이 다 끝나야 두번째 반복문이 실행되므로 두 작업이 절대 겹치지 않는다.

 

 

 

 

멀티스레드

  • 위에서 봤던 코드와 그 출력값처럼 두 작업이 번갈아 가며 실행된다.
  • 싱글스레드로 작업한 시간보다 멀티스레드로 작업한 시간이 조금 더 걸린다.
    • A작업에서 B작업으로 넘어가는 것을 context swithcing이라고 한다.
    • 실행할 작업에 대한 정보 등이 바뀌기 때문에 context switching을 할 때, 시간이 소요가 된다.
  • 멀티스레드 방식으로 작업을 하면 시간이 더 걸리는데 왜 멀티스레드 방식을 사용할까?
    • 시간이 더 걸리더라도 동시에 2가지 작업을 할 수 있다.
    • 작업을 효율적으로 관리 할 수 있다. (I/O blocking)

 

 

 

 

3. 스레드의 I/O blocking

  • I/O blocking : 입출력 시, 작업중단
  • 싱글스레드 방식에서 blocking이 발생하면 다음 작업을 진행할 수 없다.
    • 디스크에 저장돼있는 파일을 읽어올 때, 시간이 걸리는데 싱글스레드로 프로그램을 작성하면 파일을 읽어오는 그 시간동안 아무 것도 못한다.
  • 멀티스레드 방식에서 blocking이 발생하면 그냥 다른 작업을 진행할 수 있다.

 

public class Main {
    public static void main(String[] args) { // 싱글스레드
        // 작업A
        String input = JOptionPane.showInputDialog("input 입력:");
        System.out.println("입력된 input 값은 " + input);

        // 작업B
        for (int i = 10; i > 0; i--) {
            System.out.print(i);
        }
    }
}

 

 

 

 

4. 스레드 우선순위

  • 작업의 중요도에 따라 스레드의 우선순위를 다르게 하여 특정 스레드가 더 많은 작업시간을 갖게 할 수 있다.
  • 자바에서는 스레드가 1~10까지 우선순위를 보유할 수 있다.
    • 1: 최소 우선순위
    • 5: 보통 우선순위
    • 10: 최대 우선순위
  • 스레드의 우선순위를 지정해주지 않으면 보통 우선순위(5)로 지정된다.
  • 만약 우선순위를 변경하고 싶다면 setPriority() 메소드를 이용해서 변경할 수 있다.
  • 이 우선순위는 JVM에서 정해놓은 것이고 실제 Windows OS에서는 우선순위가 내부적으로 32단계로 정의되어있다.
    • 이 우선순위는 단지 희망사항에 불과하고 OS의 스케줄러에게 전달한다.
    • OS는 단지 이 우선순위를 참고만할 뿐이다. OS가 돌리는 많은 프로세스와 스레드 중에 특별히 JVM 내의 스레드만 더 우대해서 더 빨리 작업하게 해줄 순 없다.
    • 그렇기 때문에 이 우선순위에 크게 기대를 하면 안 된다. 그냥 확률적으로 더 높은 우선순위를 가진 스레드가 빨리 작업 되겠거니...(아닐 때도 있음)

 

 

 

 

5. 스레드 그룹

  • 서로 관련된 스레드를 그룹으로 묶어서 다루기 위한 것
  • 모든 스레드반드시 하나의 스레드 그룹에 포함되어 있어야 한다.
  • 스레드 그룹을 지정하지 않으면 생성한 스레드는 자동으로 <main 스레드 그룹>에 속한다.
  • 자신을 생성한 스레드(부모 스레드)의 그룹과 우선순위를 상속받는다.
    • main 스레드가 main 스레드 그룹에 속하기 때문에 우리가 생성하는 스레드는 다 main 스레드 그룹에 속한다.

 

// Thread 클래스 생성자 파라미터에 ThreadGroup 포함
    public Thread(ThreadGroup group, Runnable target, String name,
                  long stackSize) {
     }

 

 

 

 

📚 참고
자바의 정석