본문 바로가기
[JAVA]/JAVA 기본

[JAVA] 스레드(Thread)

by 팡펑퐁 2022. 9. 16.
728x90

프로세스(Process) & 스레드(Thread)

 프로세스는 실행 중인 애플리케이션(프로그램)을 의미한다. 애플리케이션이 실행되면 운영체제로부터 실행에 필요한 메모리를 할당받아 프로세스가 된다.
 프로세스는 데이터, 컴퓨터 자원, 스레드로 구성된다. 스레드는 데이터와 애플리케이션이 확보한 자원을 활용하여 소스 코드를 실행한다. 스레드는 하나의 코드 실행 흐름이라고 볼 수 있다.

 

메인 스레드(Main Thread) 

 자바 애플리케이션을 실행하면 가장 먼저 main 메서드가 실행되는데, 이는 메인 스레드가 실행시키는 것이다.  메인 스레드는 main 메서드의 코드를 처음부터 순차적으로 실행시키며, 코드의 끝에 다다르거나, return문을 만나면 실행을 종료한다.

 

<싱글 스레드와 멀티 스레드>

 

싱글 스레드 프로세스(Single-Thread Process)

 메인 스레드의 소스코드만 실행하는 애플리케이션을 싱글 스레드 프로세스라고 한다.

 

멀티 스레드 프로세스(Multi-Thread Process)

 하나의 프로세스가 여러 개의 스레드를 가져 동시에 작업을 수행할 수 있다.

 

작업 스레드 생성 & 실행

 1. Runnable 인터페이스를 구현한 객체에서 run()을 구현하여 스레드를 생성하고 실행
public class Main {
    public static void main(String[] args) {
        // Runnable 인터페이스를 구현한 객체
        Runnable task1 = new ThreadTask1();
        // task1를 인자로 전당하여 Thread 클래스를 인스턴화하여 스레드를 생성
        Thread thread1 = new Thread(task1);
        
        // 작업 스레드를 실행시킴
        thread1.start();
        // 메인 메서드의 코드
        for (int i = 0; i < 100; i++) {
            System.out.println("메인");


        }
    }
}

class ThreadTask1 implements Runnable { // Ruunable 인터페이스를 구현하는 클래스
        public void run() { // Runnable에는 run()이 정의되어 있기 때문에 반드시 구현해야한다.
            for (int i = 0; i < 100; i++) { // Run()의 메서드 바디에 새롭게 생성된 작업 스레드가 수행할 코드가 들어감
                System.out.println("작업");
            }
        }
    }

// 출력값

"메인", "작업" 뒤죽박죽 출력
 메인 스레드와 작업 스레드가 동시에 병렬로 실행되면서 "메인"과 "작업"이 뒤섞이며 출력

 

 

2. Thread 클래스를 상속받은 하위 클래스에서 run()을 구현하여 스레드를 생성하고 실행
public class Main {
    public static void main(String[] args) {
        // Thread 클래스를 상속받은 클래스를 인스턴스화하여 스레드 생성
        ThreadTask2 thread2 = new ThreadTask2();
        thread2.start(); // 작업 스레드 실행

        for (int i = 0; i < 100; i++){ //메인 스레드 실행
            System.out.println("메인");
        }
    }
}

class ThreadTask2 extends Thread { // Thread 클래스를 상속받는 클래스 작성
    public void run() { // Thread 클래스에는 run() 메서드가 정의되어 있어 run() 메서드를 오버라이딩해주어야 한다.
        for(int i = 0; i <100; i++) { // run() 메서드 바디에 스레드가 수행할 작업 내용 작성
            System.out.println("작업");
        }
    }
}

// 출력값
"메인", "작업" 뒤죽박죽 출력

 

3. 익명 객체를 사용하여 스레드를 생성하고 실행
public class Main {
    public static void main(String[] args) {
        // 익명 Runnable 구현 객체를 활용하여 스레드를 생성
        Thread thread1 = new Thread(new Runnable() {
            @Override
            public void run() {
                for (int i = 0; i < 100; i ++) {
                    System.out.print("메인");
                }
            }
        });

        thread1.start();

        for (int i = 0; i < 100; i++) {
            System.out.print("작업");
        }
    }
}

// 출력값
"메인", "작업" 뒤죽박죽 출력

 

스레드의 이름

 메인 스레드는 "main"이라는 이름을 가지고, 그 외의 스레드는 기본적으로 "Thread-n"이라는 이름을 가진다.

 

스레드의 이름 조회 

스레드의_참조변수명.getName()

스레드의 이름 설정

스레드의_참조변수명.setName()

스레드 인스턴스의 주소값 얻기

Thread.currentThread()
// Thread 클래스의 정적 메서드인 currentThread()로 주소값을 얻을 수 있다.

 

스레드 동기화

임계영역(Critical section) & 락(Lock)

 임계영역은 오직 하나의 스레드만 코드를 실행할 수 있는 코드 영역을 의미하고, 락은 임계 영역을 포함하고 있는 객체에 접근할 수 있는 권한을 의미한다.

 

임계영역 지정하기

 synchronized 키워드를 이용해 메서드 전체를 지정하거나, 특정한 영역을 임계 영역으로 지정할 수 있다.
public synchronized 메소드명(파라미터명) {...}
synchronized(객체의 참조) {...}

 

스레드의 상태와 실행 제어

  • start() : 스레드를 실행 대기 상태로 만들어준다.
  • sleep(long milliSecond) : milliSecond 동안 스레드를 일시 정지한다.
  • interrupt() : 일시 정지 상태인 스레드를 실행 대기 상태로 복귀시킨다.
  • yield() : 다른 스레드에게 실행을 양보한다.
  • join() : 다른 스레드의 작업이 끝날 때까지 기다린다.
  • wait(), notify() : 스레드 간 협업에 사용된다.
728x90

'[JAVA] > JAVA 기본' 카테고리의 다른 글

[JAVA] 배열  (0) 2022.09.17
[JAVA] 가비지 컬렉션(Garbage Collection)  (0) 2022.09.16
[JAVA] 스트림(Stream)  (0) 2022.09.16
[Java] 람다식(Lambda Expression)  (0) 2022.09.15
[JAVA] 애너테이션(Annotation)  (0) 2022.09.15