본문 바로가기
Programming/Java

[자바/Java] 쓰레드 Thread

by 코딩하는 랄로 2023. 10. 17.
728x90

Thread란

쓰레드는 프로세스안에서 독립적으로 작업을 실행하는 단위를 말한다. 프로세스란, 일반적으로 CPU에 의해 메모리에 올려져 실행중인 프로그램을 말하며, 자신만의 메모리 공간을 포함한 독립적인 실행환경을 가지고 있다.

 

자바 JVM(Java Virtual Machin)은 주로 하나의 프로세스로 실행되며, 동시에 여러 작업을 수행하기 위해 멀티 쓰레드를 지원하고 있다.

 

멀티 쓰레드란 무엇일까? 쓰레드는 프로세스안에서 작업 실행 단위라고 하였는데, JVM에 의해 관리되고, 한 프로세스에는 적어도 하나 이상의 쓰레드가 있고, Main 쓰레드를 시작으로 추가적으로 작업 실행 단위를 늘려 갈 수 있다.

 

그렇게 되면 하나의 프로세스에서 실행되는 여러 작업들을 여러 개의 실행 단위, 즉 쓰레드들이 나눠서 처리하게 되는 데 이러한 환경을 멀티 쓰레드 환경이라고 한다.

 

스레드들은 프로세스의 리소스를 공유하기 때문에 효율적이지만 여러 곳에서 접근하다보니 잠재적인 문제점에 노출될 수 있다는 단점 또한 있다.

 

 

Thread 사용

자바에서 쓰레드를 만들어서 사용하기 위해서는 두가지 방식이 있다. 하나는 Thread 클래스를 상속받는 방법과 다른 하나는 Runnable 인터페이스를 구현하는 방법이다.

 

 

Thread 클래스 상속

자바는 다중 상속을 허용하지 않기 때문에 Thread 클래스를 상속 받을 경우 다른 클래스를 상속 받지 못하기 때문에 Threa d 클래스를 직접 상속 받는 대신 Runnable 인터페이스를 이용하여 작성하는 것이 좋다.

 

  • Thread 클래스를 상속한 클래스 정의
  • run() 메소드 오버라이딩
  • 상속 받은 클래스의 객체 생성
  • start() 메소드를 통해 스레드 시작
//다른 상속 클래스가 있을 경우 implements Runnable을 통해 쓰레드 구현 가능
class MyThread extends Thread {
    @Override
    public void run() {
        //getName() : 상속 메소드
        SYstem.out.println(this.getName());
    }   
}

public class Main {
    public static void main(String[] args) {
        //쓰레드 생성
        Thread th1 = new MyThread();
        Thread th2 = new MyThread();
        
        th1.run(); //쓰레드를 실행시킨 것이 아님. run() 메소드를 실행시킨 것임
        
        //쓰레드 실행
        th1.start();
        th2.start();
        
        //해당 쓰레드 객체에 대한 start()는 딱 한번만 호출 가능
        //th1.start(); //IllegalThreadStateException 발생
    }
}

 

 

Runnable 인터페이스 구현

Runnable 인터페이스 구현 방식도 Thread를 상속받는 방식과 크게 다를 것이 없다. 위에서 언급하였듯이 Thread를 상속 받지 못하는 상황에서는 Runnable 인터페이스를 구현하여 Thread 클래스를 생성할 수 있다.

 

  • Runnable 인터페이스를 구현하는 클래스 정의
  • run() 메소드 오버라이딩
  • Runnable 객체 생성
  • Thread 객체 생성
  • start() 메소드로 시작
class MyTread implements Runnable {
    @Override
    public void run() {
        SYstem.out.println(Thread.currentThread.getName());
    }   
}

public class Main {
    public static void main(String[] args) {
        //Runnable 객체 생성
        Runnable r1 = new MyTread();
        //Thread 객체 생성
        Thread th1 = new Thread(r1);
        
        //쓰레드 실행
        th1.start();
    }
}

 

이 외에도 익명 클래스로 Runnable 인터페이스를 구현하여 사용할 수 있다.

public class Main {
    public static void main(String[] args) {

        //Thread 객체 생성
        Thread th1 = new Thread(new Runnable() {
            @Override
            public void run() {
                System.out.println(Thread.currentThread.getName());
            }
        });
        
        //쓰레드 실행
        th1.start();
    }
}

 

또한, Runnable 인터페이스는 run()  가상 메소드 하나만 가지고 있는 함수형 인터페이스로서, Lambda expression으로도 구현할 수 있다.

public class Main {
    public static void main(String[] args) {

        //Thread 객체 생성
        Thread th1 = new Thread(() -> 
            System.out.println(Thread.currentThread.getName());
        );
        
        //쓰레드 실행
        th1.start();
    }
}

 

 

Thread 메소드

Thread 객체는 여러 메소드를 가지고 있는데 static 메소드의 경우는 해당 메소드를 호출한 스레드 자신에게 적용된다는 점에 유의해야 한다.

 

  • void run( ) : 스레드의 실행코드가 작성되는 메소드로 사용자는 run() 메소드를 오버라이드 하여 사용
  • void start( ) : 스레드가 시작되도록 요청하는 메소드로 JVM은 해당 스레드의 run() 메소드를 호출 
  • void interrupt( ) : 스레드를 중지. 
  • void join( ) : 해당 스레드가 끝날때까지 기다림
  • void join(long millis) : 최대 millis 시간동안 해당 스레드가 끝날때까지 기다림
  • static void sleep(long millis) : millis 시간동안 현재 스레드를 일시중지
  • static void yield( ) : 현재 스레드의 실행시간을 다른 스레드에게 양보
  • static Thread currentThread( ) : 현재 실행중인 스레드 객체의 참조값을 반환
  • long getId( ) : 스레드의 Id를 반환
  • String getName( ) : 스레드의 이름을 반환
  • int getPriority( ) : 스레드의 우선순위 값을 반환 (우선순위 범위 : 1 ~ 10)
  • Thread.State getState( ) : 스레드의 state 값을 반환
  • ThreadGroup getThreadGroup( ) : 스레드가 속한 스레드 그룹을 반환
  • static boolean interrupted( ) : 현재 스레드의 interrupted 여부를 반환 
  • boolean isInterrupted( ) : 이 스레드의 interrupted 여부를 반환
  • boolean isAlive( ) : 이 스레드가 살아있는지 여부를 반환
  • boolean isDaemon( ) : 이 스레드가 데몬 스레드인지 여부를 반환
  • void setDaemon(boolean on) : 이 스레드를 데몬 스레드로 변경
  • void setName(String name) : 이 스레드의 이름을 name으로 변경
  • void setPriority(int newPriority) : 이 스레드의 우선순위를 newPriority로 변경
  • String toString( ) : 이 스레드의 이름, 우선순위, 스레드그룹등의 정보를 담은 문자열을 반환
728x90