[Java] 스레드 이해

2022. 10. 21. 14:40TIL💡/Java

Java에서 Thread를 구현하는 방법은 크게 두 가지가 있다.

1. Thread class 상속 → 다른 클래스 상속이 불가하니 2번 선호

2. Runnable 인터페이스 구현

public class ThreadBasic {
    public static void main(String[] args) {
        // 1. Thread Class를 상속받는 방법
        Thread t1 = new MyThread1(); // 쓰레드의 생성
        t1.start(); // 쓰레드의 실행. run()이 종료되면 MyThread1 소멸된다.
 
        // 2. Runnable 인터페이스를 구현하는 방법
        Thread t2 = new Thread(new MyThread2());
        t2.start(); // 쓰레드의 실행. run()이 종료되면 MyThread2 소멸된다.
 
    }
}
 
// 1. Thread Class를 상속받는 방법
class MyThread1 extends Thread {
    @Override
    public void run() {
        //작업할 내용
    }
}
 
// 2. Runnable 인터페이스를 구현하는 방법
class MyThread2 implements Runnable {
    @Override
    public void run() {
        //작업할 내용
    }
}

 

 

Runnable 인터페이스를 구현하는 게 일반적인 방법이다.

Runnable 인터페이스는 run()만 정의되어 있는 간단한 인터페이스이다.

Runnable 인터페이스를 구현한 경우, Runnable 인터페이스를 구현한 클래스의 인스턴스를 생성한 다음, 이 인스턴스를 Thread 클래스 생성자의 매개변수로 제공한다.

 

Thread를 생성했다고 해서 자동으로 실행되는 것은 아니다.

start() 메소드를 호출해야만 Thread가 실행된다.

Thread 동작 시 run()이 자동적으로 호출된다.

main 메소드의 작업을 수행하는 것도 Thread이며, 이를 main 쓰레드라고 한다.

public class ThreadEX1 {
    static long startTime = 0;
    public static void main(String[] args) { // ==> main 메소드의 코드를 수행하는 쓰레드
        // 모든 프로세스(실행중인 프로그램)는 최소한 하나의 쓰레드(프로세스 내에서 실제 작업을 수행)를 갖고 있다.
        // 대부분의 프로그램이 멀티쓰레드로 작성되어 있다.
        // 멀티쓰레드 장점 : 1. 시스템 자원의 효율적 사용
        // 2. 사용자에 대한 응답성 향상(채팅 중에 파일 전송)
        // 3. 작업이 분리되어 코드가 간결해진다.
        // 멀티쓰레드 단점 : 1. 동기화에 주의해야 한다. 2. 교착상태가 발생하지 않도록 해야 한다.
        // 3. 각 쓰레드가 효율적으로 고르게 실행될 수 있게 해야 한다.
 
        // 쓰레드를 생성한 후에 start()를 호출해야 쓰레드가 작업을 시작한다.
        ThreadEx1_A t1 = new ThreadEx1_A(); // 쓰레드의 생성
 
        Runnable r = new ThreadEx1_B();
        Thread t2 = new Thread(r);
 
        t1.start(); // 쓰레드 t1을 실행시킨다. ==> 새로운 호출스택 생성
        t2.start(); // 쓰레드 t2를 실행시킨다. ==> 새로운 호출스택 생성
        // 쓰레드는 순차적으로 실행되지 않고 섞여서 실행된다.
        // 실행순서는 OS 스케줄러가 결정한다.
        // 쓰레드는 '사용자 쓰레드' 와 '데몬 쓰레드' 두 종류가 있다.
        // 실행중인 사용자 쓰레드가 하나도 없을 때 프로그램은 종료된다.
 
        startTime = System.currentTimeMillis();
        try {
            t1.join();    // main쓰레드가 t1의 작업이 끝날 때까지 기다린다.
            t2.join();    // main쓰레드가 t2의 작업이 끝날 때까지 기다린다.
        } catch(InterruptedException e) {}
 
        System.out.print("소요시간:" + (System.currentTimeMillis() - ThreadEX1.startTime));
    }
}
 
class ThreadEx1_A extends Thread { // 1. 쓰레드 Class 상속
    public void run() { // Thread 클래스의 run()을 오버라이딩
        for(int i=0; i < 300; i++) {
            //System.out.println(getName()); // 조상인 Thread의 getName()을 호출
            System.out.print(new String("-"));
        }
    }
}
 
class ThreadEx1_B implements Runnable { // 2. Runnable  인터페이스 구현
    public void run() { // Runnable 인터페이스의 추상메소드 run()을 구현
        // run() : 쓰레드가 수행할 작업을 작성
        for(int i=0; i < 300; i++) {
            // Thread.currentThread() - 현재 실행중인 Thread를 반환한다.
            //System.out.println(Thread.currentThread().getName());
            System.out.print(new String("|"));
        }
    }
}

main thread

  • 모든 자바 프로그램은 메인 쓰레드가 main() 메소드가 실행하면서 시작한다.
  • return을 만나면 실행을 종료한다.
  • main thread는 작업 쓰레드를 만들어서 병렬로 코드를 실행할 수 있다.
  • 작업 쓰레드를 만들려면, Thread 클래스를 상속하거나 Runnable 인터페이스를 구현한다.
  • 멀티 쓰레드는 실행 중인 쓰레드가 하나라도 있다면, 프로세스는 종료되지 않는다.
  • 멀티 쓰레드 작업 시에는 각 쓰레드끼리 정보를 주고받을 수 있다.(프로세스끼리는 정보를 주고 받을 수 없다.)

daemon thread

  • 일반 쓰레드의 작업을 돕는 보조적인 역할을 수행한다.
  • 일반 쓰레드가 모두 종료되면 자동적으로 종료된다.
  • 가비지 컬렉터, 자동 저장, 화면 자동 갱신 등에 사용된다.
  • 무한 루프와 조건문을 이용해서 실행 후 대기하다가 특정 조건이 만족되면 작업을 수행하고 다시 대기하도록 작성한다.
  • setDaemon(boolean on)은 반드시 start()를 호출하기 전에 실행되어야 한다.

참고

https://link2me.tistory.com/1730

 

Java Thread 이해 및 Thread Life Cycle

실행중인 하나의 프로그램을 프로세스(Process)라고 한다. 프로그램을 실행하면 OS로부터 실행에 필요한 자원(메모리)를 할당받아 프로세스가 된다. 프로세스는 프로그램을 수행하는 데 필요한 데

link2me.tistory.com