[java] 자바에서 동시성(Concurrency)을 구현하는 방법

자바는 멀티스레드 환경에서 동시성을 구현할 수 있는 강력한 기능을 제공합니다. 동시성은 여러 스레드가 동시에 실행되는 상황을 의미하며, 이를 통해 프로그램의 성능과 응답성을 향상시킬 수 있습니다. 이번 포스트에서는 자바에서 동시성을 구현하는 다양한 방법에 대해 알아보겠습니다.

1. Thread 클래스 사용하기

가장 기본적인 방법은 Thread 클래스를 직접 상속받아 스레드를 구현하는 것입니다. 아래는 간단한 예제입니다.

public class MyThread extends Thread {
    public void run() {
        // 스레드가 실행할 로직 작성
    }

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

Thread 클래스는 run() 메서드를 오버라이딩하여 스레드가 실행할 로직을 구현합니다. start() 메서드를 호출하여 스레드를 시작할 수 있습니다.

2. Runnable 인터페이스 사용하기

Thread 클래스를 상속받는 대신에 Runnable 인터페이스를 구현하여 스레드를 생성할 수도 있습니다. 아래는 예제입니다.

public class MyRunnable implements Runnable {
    public void run() {
        // 스레드가 실행할 로직 작성
    }

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

Runnable 인터페이스는 run() 메서드만을 가지고 있으므로, 스레드가 실행할 로직을 구현하는 것에 집중할 수 있습니다.

3. Executor 프레임워크 사용하기

자바는 java.util.concurrent 패키지를 통해 Executor 프레임워크를 제공하여 스레드를 관리하고 작업을 스케줄링할 수 있습니다. 아래는 예제입니다.

import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

public class MyTask implements Runnable {
    public void run() {
        // 작업 로직 작성
    }

    public static void main(String[] args) {
        ExecutorService executor = Executors.newFixedThreadPool(10);
        for (int i = 0; i < 100; i++) {
            executor.execute(new MyTask());
        }
        executor.shutdown();
    }
}

ExecutorService 인터페이스를 사용하여 스레드 풀을 생성하고, execute() 메서드를 호출하여 작업을 스레드에게 할당합니다.

4. 동기화 메커니즘 사용하기

여러 스레드가 공유 데이터에 동시에 접근할 때 동기화 문제가 발생할 수 있습니다. 자바는 synchronized 키워드를 통해 동기화를 지원합니다. 아래는 예제입니다.

public class SynchronizedExample {
    private int count = 0;

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

    public int getCount() {
        return count;
    }

    public static void main(String[] args) throws InterruptedException {
        SynchronizedExample example = new SynchronizedExample();
        ExecutorService executor = Executors.newFixedThreadPool(10);
        for (int i = 0; i < 1000; i++) {
            executor.execute(() -> {
                example.increment();
            });
        }
        executor.shutdown();
        executor.awaitTermination(Long.MAX_VALUE, TimeUnit.NANOSECONDS);
        System.out.println("Count: " + example.getCount());
    }
}

increment() 메서드에 synchronized 키워드를 사용하여 동기화를 적용하였습니다. 이를 통해 여러 스레드가 각각 increment() 메서드를 호출하더라도 안전하게 count 변수를 증가시킬 수 있게 됩니다.

결론

자바에서 동시성을 구현하는 방법에 대해 알아보았습니다. Thread 클래스나 Runnable 인터페이스를 사용하여 스레드를 직접 구현하거나, Executor 프레임워크를 사용하여 스레드를 관리하고 작업을 스케줄링할 수 있습니다. 또한 동기화 메커니즘을 통해 여러 스레드가 공유 데이터에 안전하게 접근할 수 있습니다. 동시성을 적절하게 활용하여 프로그램의 성능과 응답성을 개선할 수 있도록 노력해야 합니다.

참고 자료