Thread (2)

KIHYUK MOON·2023년 2월 3일
0
post-thumbnail
post-custom-banner

Thread 상태
Thread로 객체를 생성하면 우선 실행대기 상태로 들어간다(작업을 할당받지 못한 상태). 실행대기 상태에 있는 Thread 중 선택된 Thread가 run()을 실행한다(실행상태). 이때 run() 메소드가 끝나지 않아도 다시 실행대기 상태로 돌아가며 번갈아 가며 사용할 수 있다. 경우에 따라 run 중인 Thread를 일시정지 시킬수도 있다(sleep()메소드). 일시정지 이후에는 다시 실행 대기 상태로 간다.

Thread 상태 제어

실행중인 Thread 상태를 변경하는 것을 말한다. 상태를 제어하는 메소드는 아래 그림과 같다.

주어진 시간동안 일시 정지 (sleep())

실행중인 Thread를 일정 시간 멈출 때 사용한다.

    Thread.sleep(2000);
} catch (InterruptedException e) {
    throw new RuntimeException(e);
}
try {
    Thread.sleep(2000);
} catch (InterruptedException e) {
    throw new RuntimeException(e);
}

다른 Thread의 종료를 기다림 (join())

Thread는 다른 Thread와 독립적으로 실행되는 것이 기본이지만, 다른 Thread가 종료될 때까지 기다렸다가 실행해야 하는 경우가 있다.
이런 경우에 join() 메소드를 사용한다.

public static void main(String args[]){
    SumThread sumThread = new SumThread();
    sumThread.start();
    try {
        sumThread.join();
    } catch (InterruptedException e) {
        throw new RuntimeException(e);
    }
    System.out.println("합 : " + sumThread.getSum());
}

public class SumThread extends Thread {
    private long sum;
    public long getSum() {
        return sum;
    }

    public void setSum(long sum) {
        this.sum = sum;
    }
    public void run() {
        for(int i = 0; i <= 100; i++) {
            sum += 1;
        }
    }
}

Thread 간 협엽 (wait(), notify(), notifyAll())

  • 경우에 따라 두개의 스레드가 번갈아가며 실행해야 할 경우가 있다
  • 한 스레드가 작업을 완료하면 notify() 메소드를 호출해서 일시정지 상태에 있는 다른 스레드를 실행대기 상태로 만들고, 자신은 두번째 작업을 하지 않도록 wait() 메소드를 호출한다.
  • notifyAll() 메소드는 wait()에 의해 일시정지된 모든 스레드를 실행대기 상태로 만듭니다.

Main.java

public class Main {
    public static void main(String[] args) {
        WorkObject sharedObject = new WorkObject(); // 고유 객체 생성
        ThreadA threadA = new ThreadA(sharedObject);
        ThreadB threadB = new ThreadB(sharedObject);
        threadA.start();
        threadB.start();
    }
}

WorkObject

public class WorkObject {
    public synchronized void methodA() {
        System.out.println("Thread의 methodA() 작업 실행");
        notify(); // 일시 정지에 있는 ThreadB를 실행 대기 상태로 만듦
        try {
            wait();  // ThreadA를 일시 정지 상태로 만듬
        } catch (InterruptedException e) {
        }
    }
    public synchronized void methodB() {
        System.out.println("Thread의 methodB() 작업 실행");
        notify(); // 일시 정지에 있는 ThreadA를 실행 대기 상태로 만듦
        try {
            wait();  // ThreadB를 일시 정지 상태로 만듬
        } catch (InterruptedException e) {
        }
    }
}

ThreadA

public class ThreadA extends Thread {
    private WorkObject workObject;

    public ThreadA(WorkObject workObject) {
        this.workObject = workObject;
    }

    @Override
    public void run() {
        for(int i = 0; i < 10; i++) {
            workObject.methodA();
        }
    }
}

ThreadB

public class ThreadB extends Thread {
    private WorkObject workObject;

    public ThreadB(WorkObject workObject) {
        this.workObject = workObject;
    }

    @Override
    public void run() {
        for(int i = 0; i < 10; i++) {
            workObject.methodB();
        }
    }
}

Thread의 안전한 종료 (stop 플래그, interrupt())

stop 플래그를 이용하는 방법

Main

public class Main {
    public static void main(String[]args) throws InterruptedException {
        RunTread runTread = new RunTread();
        runTread.start();
        Thread.sleep(1000);
        runTread.setStop(true);
    }
}

**RunThread

public class RunTread extends Thread {
    private boolean stop; // stop 플래그 설정

    public void setStop(boolean stop) {
        this.stop = stop;
    }

    public void run() {
        while(!stop) {
            System.out.println("Thread 실행 중...");
        }
        System.out.println("자원 정리");
        System.out.println("실행 종료");
    }
}

interrupt() 메소드 이용방법
interrupt 메소드는 스레드가 일시정지 상태에 있을 때 InterruptException 예외를 발생시키다.
이것을 이용해 run() 메소드를 정상 종료 시킬 수 있다.

Main

public class Main {
    public static void main(String[]args) {
        InterruptThread interThread = new InterruptThread();
        interThread.start();
        try {
            Thread.sleep(1000);
        } catch(InterruptedException e) { }
        interThread.interrupt();
    }
}

InterruptThread

public class InterruptThread extends Thread {
    public void run() {
        try {
            while(true) {
                System.out.println("쓰레드 실행 중...");
                Thread.sleep(1);
            }
        } catch(InterruptedException e) {
        }
        System.out.println("자원 정리");
        System.out.println("실행 종료");
    }
}
profile
개발자 전직중..
post-custom-banner

0개의 댓글