본문 바로가기

IT 개발/JAVA

Java 멀티스레딩 개념 및 활용: 스레드 생성, 동기화

Java에서 멀티스레딩은 여러 개의 스레드를 동시에 실행할 수 있는 프로그래밍 기법입니다. 멀티스레딩을 활용하면 동시성(concurrency)과 병렬성(parallelism)을 향상시켜 프로그램의 성능을 높일 수 있습니다. 이 글에서는 Java에서의 멀티스레딩 개념과 활용 방법을 설명하고 예시를 통해 알아보겠습니다.

 

1. 스레드 생성

Java에서 스레드를 생성하는 두 가지 방법은 다음과 같습니다.

 

1.1. Thread 클래스 상속

Thread 클래스를 상속받아 run() 메서드를 재정의(override)하여 스레드를 생성할 수 있습니다.

class MyThread extends Thread {
  @Override
  public void run() {
    // 스레드에서 실행되는 코드
  }
}

public class App {
  public static void main(String[] args) {
    MyThread myThread = new MyThread();
    myThread.start(); // 스레드 실행
  }
}

 

1.2. Runnable 인터페이스 구현

Runnable 인터페이스를 구현하여 run() 메서드를 정의하고 Thread 객체를 생성할 때 인스턴스를 전달하여 스레드를 실행할 수 있습니다.

class MyRunnable implements Runnable {
  @Override
  public void run() {
    // 스레드에서 실행되는 코드
  }
}

public class App {
  public static void main(String[] args) {
    MyRunnable myRunnable = new MyRunnable();
    Thread myThread = new Thread(myRunnable);
    myThread.start(); // 스레드 실행
  }
}

 

두 가지 방법 중 어느 것을 선택하든 상관없지만, Runnable 인터페이스를 구현하는 방식은 다중 상속을 허용하여 코드의 유연성이 높아집니다.

 

 

2. 스레드 동기화

멀티스레딩 환경에서 여러 스레드가 공유 데이터에 동시에 접근할 때 발생할 수 있는 문제를 해결하기 위해 동기화(synchronization)가 필요합니다. Java에서 동기화는 synchronized 키워드를 사용하여 구현할 수 있습니다.

 

2.1. synchronized 메서드

메서드의 선언부에 synchronized 키워드를 추가하여 동기화된 메서드를 생성할 수 있습니다. 동기화된 메서드는 한 번에 한 스레드만 접근 가능합니다.

public class Counter {
  private int count = 0;

  public synchronized void increment() {
    count++;
  }

  public synchronized void decrement() {
    count--;
  }

  public synchronized int getCount() {
    return count;
  }
}

 

2.2. synchronized 블록

Synchronized 키워드를 사용해 코드 블록을 생성할 수 있습니다. synchronized 블록은 한 번에 한 스레드만 해당 코드 블록을 실행할 수 있도록 합니다.

public class Counter {
  private int count = 0;

  public void increment() {
    synchronized (this) {
      count++;
    }
  }

  public void decrement() {
    synchronized (this) {
      count--;
    }
  }

  public int getCount() {
    synchronized (this) {
      return count;
    }
  }
}

 

 

3. Thread 기본 메서드

멀티스레딩을 사용할 때 주요 스레드 메서드를 활용할 수 있습니다.

 

3.1. yield()

현재 스레드에서 실행 중인 작업이 포기되고 대기 상태로 전환되어 실행기회를 다른 스레드에 양보할 수 있습니다.

public void run() {
  for (int i = 0; i < 5; i++) {
    System.out.println(Thread.currentThread().getName() + " 실행 중...");
    
    if (i == 2) {
      Thread.yield();
    }
  }
}

 

3.2. join()

특정 스레드가 끝날 때까지 현재 스레드를 일시 중지할 수 있습니다.

public class App {
  public static void main(String[] args) {
    MyThread myThread = new MyThread();
    myThread.start();

    try {
      myThread.join();
    } catch (InterruptedException e) {
      e.printStackTrace();
    }

    System.out.println("메인 스레드 종료");
  }
}

 

 

Java의 멀티스레딩을 이해하고 활용하면 동시성과 병렬성을 높일 수 있어 프로그램의 성능 향상이 가능합니다. 스레드 생성 방법, 동기화, 기본 메서드 활용 등을 공부하며 다양한 프로그래밍 상황에서 멀티스레딩을 적용해보기를 권장합니다.