계산기 과제로 불탔던 머리도 식힐겸 지난 강의에서 다뤘던 Thread에 대해서 정리해보는 하루를 가져보자.

Thread?

Thread란 쉽게 말해 프로세스를 실행하기 위한 실행 단위? 라고 할 수 있겠다.
강의에서는 일꾼이라고 표현하는데 그 말이 딱 맞는 것 같다.

Single vs Multi

single

프로세스 안에서 하나의 쓰레드만 실행
  • Java 프로그램의 경우 main() 메서드만 실행시켰을 때 이것을 싱글 쓰레드 라고 합니다.
  • 지금까지 코드스니펫을 통해 실습한 모든 Java 프로그램들은 main() 메서드만 실행시켰기 때문에 모두 싱글 쓰레드로 실행되고 있었습니다.
    • Java 프로그램 main() 메서드의 쓰레드를 ‘메인 쓰레드’ 라고 부릅니다.
    • JVM의 메인 쓰레드가 종료되면, JVM도 같이 종료됩니다.

multi

프로세스 안에서 여러개의 쓰레드가 실행
  • 하나의 프로세스는 여러 개의 실행 단위(쓰레드)를 가질 수 있으며 이 쓰레드들은 프로세스의 자원을 공유합니다.
  • Java 프로그램은 메인 쓰레드 외에 다른 작업 쓰레드들을 생성하여 여러 개의 실행 흐름을 만들 수 있습니다.
  • 멀티 쓰레드 장점
    • 여러 개의 쓰레드(실행 흐름)을 통해 여러 개의 작업을 동시에 할 수 있어서 성능이 좋아집니다.
    • 스택을 제외한 모든 영역에서 메모리를 공유하기 때문에 자원을 보다 효율적으로 사용할 수 있습니다.
    • 응답 쓰레드와 작업 쓰레드를 분리하여 빠르게 응답을 줄 수 있습니다. (비동기)
  • 멀티 쓰레드 단점
    • 동기화 문제가 발생할 수 있습니다.
      • 프로세스의 자원을 공유하면서 작업을 처리하기 때문에 자원을 서로 사용하려고 하는 충돌이 발생하는 경우를 의미합니다.
    • 교착 상태(데드락)이 발생할 수 있습니다.
      • 둘 이상의 쓰레드가 서로의 자원을 원하는 상태가 되었을 때 서로 작업이 종료되기만을 기다리며 작업을 더 이상 진행하지 못하게 되는 상태를 의미합니다.

Thread와 Runnable

Thread

📌 Java에서 제공하는 Thread 클래스를 상속받아 쓰레드를 구현
<public class TestThread extends Thread {
				@Override
				public void run() {
							// 쓰레드 수행작업
				}
}

...

TestThread thread = new TestThread(); // 쓰레드 생성
thread.start() // 쓰레드 실행

여기서 핵심은 run() 메서드.
run() 메서드에 작성된 코드가 쓰레드가 수행할 작업이다.

Runnable

📌Java에서 제공하는 Runnable 인터페이스를 사용하여 쓰레드를 구현
<public class TestRunnable implements Runnable {
				@Override
				public void run() {
							// 쓰레드 수행작업 
				}
}

...

Runnable run = new TestRunnable();
Thread thread = new Thread(run); // 쓰레드 생성

thread.start(); // 쓰레드 실행

위의 경우는, Thread를 직접 받아 상속하는 경우.
이 경우는 Runnable 인터페이스를 통해 구현하는 경우.
확장성을 위해서 인터페이스를 통한 구현이 매우 유리하다.

Daemon vs User

User Thread

사용자스레드(user thread)는 foreground에서 실행되는 높은 우선순위를 가진 스레드입니다. 자바 프로그램을 실행시키면 JVM은 main()메서드가 실행되는 main스레드를 생성하는데 이 main스레드가 사용자스레드입니다. 그리고 main스레드에서 새로운 스레드를 생성하게 되면 부모 스레드의 속성을 상속받아 기본적으로 사용자스레드가 되며, 이렇게 생성된 사용자스레드들이 모두 종료하게 되면 그 프로그램은 종료하게 됩니다. 

Daemon Thread 

데몬스레드(daemon thread)는 background에서 실행되는 낮은 우선순위를 가진 스레드입니다. 주로 보조적인 역할을 담당하는데 사용되며, 자바에서 메모리 정리를 해주는 가비지 컬렉터(garbage collector)가 대표적인 데몬스레드입니다. 데몬스레드와 사용자스레드의 가장 큰 차이점은 JVM이 데몬스레드가 작업이 끝날때까지 기다리지 않는다는 점입니다. 사용자스레드가 모두 종료되면 데몬스레드는 자동으로 종료됩니다.

public class Main {
    public static void main(String[] args) {
        Runnable demon = () -> {
            for (int i = 0; i < 1000000; i++) {
                System.out.println("demon");
            }
        };

        Thread thread = new Thread(demon);
        thread.setDaemon(true); // true로 설정시 데몬스레드로 실행됨

        thread.start();

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

데몬 쓰레드에는 for문이 백만번으로 설정 되어 있지만, 사용자 쓰레드인 main 쓰레드가 100번 for문을 반복하면 따라서 종료되게 된다.

Priority

Priority

📌 쓰레드 작업의 중요도에 따라서 쓰레드의 우선순위를 부여할 수 있습니다.
		: 작업의 중요도가 높을 때 우선순위를 높게 지정하면 더 많은 작업시간을 부여받아 빠르게 처리될 수 있습니다.

최소 우선순위 (MIN_PRIORITY) = 1 << 보통 우선순위 (NROM_PRIORITY) = 5 
		<< 최대 우선순위 (MAX_PRIORITY) = 10
생성 시 기본 값(default)은 보통 우선순위
profile
둘뺌

0개의 댓글

관련 채용 정보