Logo

자바 쓰레드

본 포스팅는 오라클 자바 튜토리얼의 Thread ObjectsDefining and Starting a Thread를 번역하였습니다.

쓰레드 객체

모든 쓰레드는 Thread 클래스의 인스턴스와 관계를 갖습니다. 동시 애플리케이션(concurrent application)을 개발하기 위해서 쓰레드 객체를 사용하는데는 두 가지 기본 전략이 있습니다.

  • 쓰레드의 생성과 관리를 직접 제어하기 위해서, 애플리케이션이 비동기 작업이 필요할 때 마다 단순히 Thread 클래스의 인스턴스를 만들 수 있습니다.
  • 응용 프로그램으로 부터 쓰레드 관리를 분리하고 추상화하기 위해서, 비동기 작업들을 executor에게 위임할 수 있습니다.

본 섹션은 Thread 객체의 사용에 대해서 문서화하겠습니다. Executors는 고수준 동시성 객체(high-level concurrency objects) 섹션에서 별도로 다루겠습니다.

쓰레드를 정의하고 시작하기

Thread 인스턴스를 생성하는 응용 프로그램은 반드시 해당 쓰레드 상에서 수행될 코드를 제공해야 합니다. 다음과 같이 2가지 방법이 있습니다.

Runnable 인터페이스를 구현하기

Runnable 인터페이스는 쓰레드 상에서 수행될 코드를 담기 위한 run()이라는 하나의 메서드만을 정의하고 있습니다. 다음 HelloRunnalbe 예제와 같이 Runnalbe 객체는 Thread 클래스의 생성자로 넘어오게 됩니다.

public class HelloRunnable implements Runnable {

  public void run() {
    System.out.println("Hello from a thread!");
  }

  public static void main(String args[]) {
    (new Thread(new HelloRunnable())).start();
  }

}

Thread 클래스를 상속하기

Thread 클래스 자체도 Runnable 인터페이스를 구현하고 있으나 run() 메소드는 아무 것도 하지 않도록 되어 있습니다. 다음 HelloThread 예제와 같이 run() 메소드에 대한 자체 구현을 제공함으로써 Thread 클래스를 상속할 수 있습니다.

public class HelloThread extends Thread {

  public void run() {
    System.out.println("Hello from a thread!");
  }

  public static void main(String args[]) {
    (new HelloThread()).start();
  }

}

두 가지 예제 모두 새로운 쓰레드를 시작하기 위해서 Thread.start() 메소드를 호출하고 있다는 것에 주목하세요.

그럼 과연 어떤 방식을 사용해야 할까요? Runnable 인터페이스를 구현하면 Thread 클래스 외에 다른 클래스도 상속할 수 있기 때문에 Runnable 객체를 사용하는 첫번째 방식이 더 보편적입니다. 두번째 방식은 간단한 애플리케이션에서 사용하기 더 쉽지만, 해당 작업 클래스가 Thread 클래스의 후손이 되어야 한다는 제한이 있습니다. 본 수업에서는 Runnable 작업을 그 작업을 실행시켜주는 Thread 객체로부터 분리하여 접근하는 첫번째 방식에 초점을 맞추겠습니다. 이러한 접근법이 더 유연한 뿐만 아니라, 나중에 다룰 고수준의 쓰레드의 관리 API에서도 더 적용이 용이합니다.

Thread 클래스는 쓰레드 관리를 위한 많은 메소드를 정의하고 있습니다. 이 메소드들은 해당 메소드를 호출하는 대상 쓰레드와 관련된 정보를 제공거나 대상 쓰레드의 상태에 영향을 주는 정적 메소드를 포함합니다. 다른 메소드들은 해당 쓰레드와 Thread 객체를 관리하는데 관여하고 있는 다른 쓰레드로 부터 호출되어집니다. 이어지는 섹션에서 이 메소드들을 살펴보도록 하겠습니다.