[JAVA] Thread

in·2023년 9월 1일
0

JAVA

목록 보기
6/9

스레드(Thread)

프로세스 안에서 실질적으로 작업을 실행하는 단위

✔️ 프로세스 : CPU에 의해 메모리에 올라가 실행 중인 프로그램

멀티스레딩

하나의 프로세스 안에 여러 개의 스레드가 동시에 작업을 수행하는 것

스레드 구현

Runnable 인터페이스 구현

public class MyThread implements Runnable {
    @Override
    public void run() {
        // 수행 코드
    }
}

Thread 클래스 생성

public class MyThread extends Thread {
    @Override
    public void run() {
        // 수행 코드
    }
}

스레드 생성

스레드 생성 주기

Runnable 상태 : 스레드가 실행되기위한 준비 단계
Running 상태 : 스케줄러에 의해 선택된 스레드가 실행되는 단계
Blocked 상태 : 스레드가 작업을 완수하지 못하고 잠시 작업을 멈추는 단계

Runnable 인터페이스 구현

  • 해당 클래스를 인스턴스화해서 Thread 생성자에 argument로 넘겨줘야 함
  • run()을 호출하면 Runnable 인터페이스에서 구현한 run()이 호출되므로 따로 오버라이딩하지 않아도 되는 장점이 있음
    public static void main(String[] args) {
       Runnable r = new MyThread();
       Thread t = new Thread(r, "mythread");
    }

Thread 클래스 상속

  • 상속받은 클래스 자체를 스레드로 사용할 수 있음
  • Thread를 상속받으면 스레드 클래스의 메소드(getName())를 바로 사용할 수 있지만, Runnable 구현의 경우 Thread 클래스의 static 메소드인 currentThread()를 호출하여 현재 스레드에 대한 참조를 얻어와야만 호출 가능
    public class ThreadTest implements Runnable {
       public ThreadTest() {}
       
       public ThreadTest(String name){
           Thread t = new Thread(this, name);
           t.start();
       }
       
       @Override
       public void run() {
           for(int i = 0; i <= 50; i++) {
               System.out.print(i + ":" + Thread.currentThread().getName() + " ");
               try {
                   Thread.sleep(100);
               } catch (InterruptedException e) {
                   e.printStackTrace();
               }
           }
       }
    }

스레드 실행

run() 호출이 아닌 start() 호출로 해야함

start()는 스레드가 작업을 실행하는데 필요한 콜 스택을 생성한 다음 run()을 호출해서 그 스택 안에 run()을 저장할 수 있도록 해줌

스레드 실행제어

스레드의 상태

  • NEW : 스레드가 생성되고 아직 start()가 호출되지 않은 상태
  • RUNNABLE : 실행 중 또는 실행 가능 상태
  • BLOCKED : 동기화 블럭에 의해 일시정지된 상태(lock이 풀릴 때까지 기다림)
  • WAITING, TIME_WAITING : 실행가능하지 않은 일시정지 상태
  • TERMINATED : 스레드 작업이 종료된 상태

스케줄링과 관련된 메소드

sleep(), join(), yield(), interrupt()

동기화

여러 스레드가 동일한 리소스를 공유하여 사용하게 되면 서로의 결과에 영향을 주기 때문에 이를 방지하는 기법
➡️ 임계 영역(critical section)과 잠금(lock) 활용

동기화 방법

  • 임계 영역(critical section) : 공유 자원에 단 하나의 스레드만 접근하도록 함(하나의 프로세스에 속하 스레드만 가능)
  • 뮤텍스(mutex) : 공유 자원에 단 하나의 스레드만 접근하도록 함(서로 다른 프로세스에 속한 스레드도 가능)
  • 이벤트(event) : 특정한 사건 발생을 다른 스레드에게 알림
  • 세마포어(semaphore) : 한정된 개수의 자우너을 여러 스레드가 사용하려고 할 때 접근 제한
  • 대기 가능 타이머(waitable timer) : 특정 시간이 되면 대기 중이던 스레드 꺠움

synchronized 활용

synchronized 활용하여 임계영역 설정

  • 서로 다른 두 객체가 동기화를 하지 않은 메소드를 같이 오버라이딩해서 이용하면 두 스레드가 동시에 진행되므로 원하는 출력값을 얻지 못함
    ➡️ 이때 오버라이딩되는 부모 클래스의 메소드에 synchronized 키워드로 임계영역 설정하면 해결 가능

[참고 자료]

🔗링크1
🔗링크2

0개의 댓글