[JAVA] 고급 1편 (멀티스레드와 동시성) 2 - 스레드 생성과 실행

호호빵·2024년 11월 16일
0

1 .스레드 생성

  • 스레드를 생성하는 방법에는 Thread를 상속받는 방법과 Runnable 인터페이스를 구현하는 방법이 있음

// Thread 상속
public class HelloThread extends Thread {

    @Override
    public void run() {
        System.out.println(Thread.currentThread().getName() +  ": run()");
    }
}

// Runnable 인터페이스 구현
public class HelloRunnable implements Runnable {
    
    @Override
    public void run() {
        System.out.println(Thread.currentThread().getName() + ": run()");
    }
}

// start()로 실행
public class HelloRunnableMain {
    public static void main(String[] args) {
        System.out.println(Thread.currentThread().getName() + ": main() start");

        HelloRunnable runnable = new HelloRunnable();
        Thread thread = new Thread(runnable);
        thread.start();

        System.out.println(Thread.currentThread().getName() + ": main() end");
    }
}
  • 스레드 생성 전

    • 자바는 실행 시점에 main이라는 이름의 스레드를 만들고 프로그램의 시작점인 main() 메서드 실행
  • 스레드 생성 후

    • 스레드 객체를 생성하고 반드시 start()를 호출해야 스택 공간을 할당받고 스레드가 작동함
    • 스레드에 이름을 주지않으면 Thread-0, Thread-1과 같은 임의의 이름을 부여함
    • Thread-0 스레드는 run() 메서드의 스택 프레임을 스택에 올리면서 run() 메서드를 시작함
    • 스레드는 순서와 실행 기간을 보장하지 않음 → 멀티 스레드임을 알 수 있음

Thread 상속 vs Runnable 구현

  • Thread 클래스 상속 방식
    • 장점
      • 간단한 구현: Thread 클래스를 상속받아 run() 메서드만 재정의하면 된다.
    • 단점
      • 상속의 제한: 자바는 단일 상속만을 허용하므로 이미 다른 클래스를 상속받고 있는 경우 Thread 클래스를 상속받을 수 없다.
      • 유연성 부족: 인터페이스를 사용하는 방법에 비해 유연성이 떨어진다.
  • Runnable 인터페이스를 구현 방식
    • 장점
      • 상속의 자유로움: Runnable 인터페이스 방식은 다른 클래스를 상속받아도 문제없이 구현할 수 있다.
      • 코드의 분리: 스레드와 실행할 작업을 분리하여 코드의 가독성을 높일 수 있다.
      • 여러 스레드가 동일한 Runnable 객체를 공유할 수 있어 자원 관리를 효율적으로 할 수 있다.
    • 단점
      • 코드가 약간 복잡해질 수 있다. Runnable 객체를 생성하고 이를 Thread 에 전달하는 과정이 추가된다.




2. 데몬 스레드

  • 스레드는 사용자 스레드와 데몬 스레드 2가지 종류로 구분 가능
  • 사용자 스레드 (User Thread)
    • 프로그래의 주요 작업을 수행함
    • 작업이 완료될 때까지 실행됨
    • 모든 user스레드가 종료되면 JVM도 종료됨
  • 데몬 스레드 (daemon Thread)
    • 백그라운드에서 보조적인 작업 수행
    • 모든 user스레드가 종료되면 데몬 스레드는 자동으로 종료됨
    • JVM은 데몬 스레드의 실행 완료를 기다리지 않고 종료됨
    • 접적으로 보이지 않으면서 시스템의 백그라운드에서 작업을 수행하는 것을 데몬 스레드, 데몬 프로세스라 함





3 .Runnable을 만드는 다양한 방법

i) 정적 중첩 클래스 사용

  • 특정 클래스 안에서만 사용되는 경우 중첩 클래스 사용
    public class InnerRunnableMainV1 {
        public static void main(String[] args) {
            log("main() start");
    
            Runnable runnable = new MyRunnable();
            Thread thread = new Thread(runnable);
            thread.start();
    
            log("main() end");
        }
    
        static class **MyRunnable** implements Runnable {
    
            @Override
            public void run() {
                log("run()");
            }
        }
    }

ii) 익명 클래스 사용

  • 특정 메서드 안에서만 간단히 정의하고 사용하고 싶다면 익명 클래스 사용하면 됨

iii) 람다 사용

  • 람다를 사용하면 메서드 코드 조각 전달 가능
public class InnerRunnableMainV4 {
    public static void main(String[] args) {
        log("main() start");
        
        Thread thread = new Thread(() -> log("run()"));
        thread.start();
        
        log("main() end");
    }
}









Reference

자바 고급 1편 - 멀티스레드와 동시성

profile
하루에 한 개념씩

0개의 댓글