Java Thread

Seongmin·2022년 12월 28일
0

CS

목록 보기
5/6

참고 : program / process / thread
https://velog.io/@seongmin42/program-process-thread

Java Thread

  • 일반 스레드와 거의 차이가 없으며, JVM가 운영체제의 역할을 한다.
  • 자바에는 프로세스가 존재하지 않고 스레드만 존재하며, 자바 스레드는 JVM에 의해 스케줄되는 실행 단위 코드 블록이다.
  • JVM의 역할
    • 스레드가 몇 개 존재하는지
    • 스레드로 실행되는 프로그램 코드의 메모리 위치는 어디인지
    • 스레드의 상태는 무엇인지
    • 스레드 우선순위는 얼마인지
  • 즉, 개발자는 자바 스레드로 작동할 스레드 코드를 작성하고, 스레드 코드가 생명을 가지고 실행을 시작하도록 JVM에 요청하는 일 뿐이다.

Thread

public class SampleThread extends Thread {
    int seq;

    public SampleThread(int seq) {
        this.seq = seq;
    }

    public void run() {
        System.out.println(this.seq + " thread start.");  // 쓰레드 시작
        try {
            Thread.sleep(1000);  // 1초 대기
        } catch (Exception e) {
        }
        System.out.println(this.seq + " thread end.");  // 쓰레드 종료 
    }

    public static void main(String[] args) {
        for (int i = 0; i < 10; i++) {  // 총 10개의 쓰레드를 생성하여 실행한다.
            Thread t = new SampleThread(i);
            t.start();
        }
        System.out.println("main end.");  // main 메서드 종료
    }
}
0 thread start.
5 thread start.
4 thread start.
1 thread start.
3 thread start.
2 thread start.
9 thread start.
7 thread start.
main end.
6 thread start.
8 thread start.
5 thread end.
4 thread end.
8 thread end.
6 thread end.
7 thread end.
1 thread end.
9 thread end.
2 thread end.
3 thread end.
0 thread end.

sampleThread.start()를 실행하면 sampleThreadrun()메서드가 수행된다. 다만, 쓰레드는 순서대로 실행되지 않고, 순서와 상관없이 동시에 실행된다. 특히 main 메서드는 쓰레드가 종료되기 전에 종료됐다.

Join

모든 쓰레드가 종료된 후에 main 메서드를 종료시키기 위해, join() 메서드가 필요하다.

import java.util.ArrayList;

public class SampleThread extends Thread {
    int seq;
    public SampleThread(int seq) {
        this.seq = seq;
    }

    public void run() {
        System.out.println(this.seq+" thread start.");
        try {
            Thread.sleep(1000 * this.seq);
        }catch(Exception e) {
        }
        System.out.println(this.seq+" thread end.");
    }

    public static void main(String[] args) {
        ArrayList<Thread> threads = new ArrayList<>();
        for(int i=0; i<10; i++) {
            Thread t = new SampleThread(i);
            t.start();
            threads.add(t);
        }

        for(int i=0; i<threads.size(); i++) {
            Thread t = threads.get(i);
            try {
                t.join(); // t 쓰레드가 종료할 때까지 기다린다.
            }catch(Exception e) {
            }
        }
        System.out.println("main end.");
    }
}
0 thread start.
2 thread start.
1 thread start.
4 thread start.
7 thread start.
3 thread start.
5 thread start.
0 thread end.
9 thread start.
8 thread start.
6 thread start.
1 thread end.
2 thread end.
3 thread end.
4 thread end.
5 thread end.
6 thread end.
7 thread end.
8 thread end.
9 thread end.
main end.

join() 메서드는 쓰레드가 종료될 때까지 기다리게 하는 메서드이다. 쓰레드가 종료된 후 그 다음 로직을 수행해야 할 때 필요한 메서드이다.

Runnable

자바에서는 인터페이스만이 다중 상속이 가능하기 때문에, 보통 쓰레드를 Runnable 인터페이스를 구현하는 방식으로 사용한다.

import java.util.ArrayList;

public class SampleThread implements Runnable {
    int seq;
    public SampleThread(int seq) {
        this.seq = seq;
    }

    public void run() {
        System.out.println(this.seq+" thread start.");
        try {
            Thread.sleep(1000);
        }catch(Exception e) {
        }
        System.out.println(this.seq+" thread end.");
    }

    public static void main(String[] args) {
        ArrayList<Thread> threads = new ArrayList<>();
        for(int i=0; i<10; i++) {
            Thread t = new Thread(new SampleThread(i));
            t.start();
            threads.add(t);
        }

        for(int i=0; i<threads.size(); i++) {
            Thread t = threads.get(i);
            try {
                t.join();
            }catch(Exception e) {
            }
        }
        System.out.println("main end.");
    }
}
3 thread start.
6 thread start.
1 thread start.
2 thread start.
7 thread start.
8 thread start.
5 thread start.
4 thread start.
0 thread start.
9 thread start.
6 thread end.
2 thread end.
3 thread end.
1 thread end.
8 thread end.
7 thread end.
4 thread end.
0 thread end.
9 thread end.
5 thread end.
main end.

위의 방식은 Thread의 생성자로 Runnable 인터페이스를 구현한 객체를 넘기는 방법이다. Thread 객체를 상속하는 것보다 유연한 방법이다.

Thread의 상태

위에서 알 수 있듯, 쓰레드는 순서에 영향을 받지 않는다. start()가 호출되었다고 바로 실행되는 구조가 아니기 때문이다. 우선 실행대기 상태에 들어가게 되며, OS 스케쥴러에 의해 결정된 스케쥴에 따라 자신의 차례가 오면 실행되는 구조이다.

스레드의 상태는 다음과 같다.

  • NEW : 쓰레드 객체가 생성된 상태, 아직 시작되지 않은 상태다
  • RUNNABLE : 쓰레드가 실행중인 상태
  • BLOCKED : 쓰레드가 실행 중지 상태이며, 모니터 락(monitor lock)이 풀리기를 기다리는 상태
  • WAITING : 쓰레드가 대기중인 상태
  • TIMED_WAITING : 특정 시간만큼 쓰레드가 대기중인 상태
  • TERMINATED : 쓰레드가 종료된 상태

자세한 내용은 https://velog.io/@khsb2012/java-study-week10 참고

출처


https://wikidocs.net/230
https://velog.io/@khsb2012/java-study-week10

0개의 댓글