# 자바 동시성(Concurrency) API 정리 및 쉬운 설명 자바의 동시성(Concurrency) API는 **멀티스레딩을 효율적으로 관리하고 안전하게 실행할 수 있도록 지원하는 기능**을 제공한다. 즉, **여러 작업을 동시에 실행하여 프로그램 성능을 향상**시킬 수 있다. --- ## 1. 주요 클래스 및 메서드 정리 ### (1) `Thread` 클래스 (기본 스레드 실행) | 메서드 | 설명 | |--------|------------------------------| | `start()` | 새로운 스레드를 실행 | | `run()` | 실행할 코드 정의 (직접 호출하면 동작하지 않음) | | `sleep(ms)` | 지정된 시간(ms) 동안 스레드 일시 정지 | | `join()` | 현재 스레드가 종료될 때까지 다른 스레드 대기 | | `interrupt()` | 실행 중인 스레드를 인터럽트 (깨우기) | | `isAlive()` | 스레드가 실행 중인지 확인 | **사용 예시:** ```java class MyThread extends Thread { public void run() { System.out.println("스레드 실행 중!"); } } MyThread t = new MyThread(); t.start(); // 스레드 실행 ``` --- ### (2) `Runnable` 인터페이스 (스레드 실행) | 메서드 | 설명 | |--------|------------------------------| | `run()` | 실행할 코드 정의 | **사용 예시:** ```java class MyRunnable implements Runnable { public void run() { System.out.println("Runnable 스레드 실행!"); } } Thread t = new Thread(new MyRunnable()); t.start(); ``` → `Thread` 클래스를 직접 상속하지 않고 `Runnable`을 구현하여 사용. --- ### (3) `ExecutorService` (스레드 풀) | 메서드 | 설명 | |--------|------------------------------| | `submit(Runnable)` | 스레드를 실행 (결과 없음) | | `submit(Callable)` | 스레드를 실행하고 결과 반환 | | `shutdown()` | 스레드 풀 종료 (기존 작업 수행 후 종료) | | `shutdownNow()` | 즉시 모든 작업 중단 | **사용 예시:** ```java ExecutorService executor = Executors.newFixedThreadPool(2); executor.submit(() -> System.out.println("스레드 풀에서 실행")); executor.shutdown(); ``` → `Executors.newFixedThreadPool(2)`를 사용해 2개의 스레드를 관리. --- ### (4) `Callable` & `Future` (결과 반환이 필요한 작업) | 메서드 | 설명 | |--------|------------------------------| | `call()` | 실행할 코드 정의, 결과 반환 | | `get()` | `Future`에서 결과 가져오기 (블로킹) | | `isDone()` | 작업 완료 여부 확인 | **사용 예시:** ```java Callable task = () -> { Thread.sleep(1000); return 10; }; ExecutorService executor = Executors.newSingleThreadExecutor(); Future future = executor.submit(task); System.out.println(future.get()); // 결과 가져오기 executor.shutdown(); ``` → `Callable`을 사용하면 **스레드 실행 후 결과 값을 반환**할 수 있음. --- ### (5) `ReentrantLock` (락을 이용한 동기화) | 메서드 | 설명 | |--------|------------------------------| | `lock()` | 락 획득 | | `unlock()` | 락 해제 | | `tryLock()` | 락을 시도하고 성공하면 `true` 반환 | **사용 예시:** ```java ReentrantLock lock = new ReentrantLock(); lock.lock(); try { System.out.println("임계영역 실행"); } finally { lock.unlock(); } ``` → `synchronized` 키워드 대신 `ReentrantLock`을 사용하여 더 정교한 동기화 가능. --- ### (6) `Semaphore` (동시 실행 제한) | 메서드 | 설명 | |--------|------------------------------| | `acquire()` | 리소스 사용 요청 (없으면 대기) | | `release()` | 사용한 리소스 반환 | **사용 예시:** ```java Semaphore semaphore = new Semaphore(2); semaphore.acquire(); // 사용 가능하면 진행, 아니면 대기 System.out.println("리소스 사용 중"); semaphore.release(); ``` → 한 번에 2개의 스레드만 특정 코드 실행 가능. --- ### (7) `CountDownLatch` (스레드가 모두 끝날 때까지 대기) | 메서드 | 설명 | |--------|------------------------------| | `await()` | 모든 스레드가 완료될 때까지 대기 | | `countDown()` | 하나의 작업 완료 처리 | **사용 예시:** ```java CountDownLatch latch = new CountDownLatch(3); for (int i = 0; i < 3; i++) { new Thread(() -> { System.out.println("작업 완료"); latch.countDown(); }).start(); } latch.await(); System.out.println("모든 작업 완료"); ``` → 모든 작업(`countDown()` 3회)이 끝나야 `await()`이 풀림. --- ### (8) `CyclicBarrier` (스레드가 모두 도달할 때까지 대기) | 메서드 | 설명 | |--------|------------------------------| | `await()` | 지정된 개수의 스레드가 모일 때까지 대기 | **사용 예시:** ```java CyclicBarrier barrier = new CyclicBarrier(3, () -> { System.out.println("모든 스레드 도착!"); }); for (int i = 0; i < 3; i++) { new Thread(() -> { System.out.println("스레드 실행 중"); barrier.await(); }).start(); } ``` → `CyclicBarrier`는 정해진 개수의 스레드가 모두 도착할 때까지 기다림. --- ## 2. 자바 동시성 쉽게 설명하기 자바에서 동시성을 다룰 때 중요한 개념은 **멀티스레딩과 스레드 동기화**다. 즉, 여러 개의 스레드가 **같은 자원을 동시에 접근하면 충돌이 발생**할 수 있으므로, 이를 적절히 제어해야 한다. ### 1️⃣ **기본적인 멀티스레드** - `Thread` 또는 `Runnable`을 사용해 실행 - `start()`로 실행, `join()`으로 대기 ### 2️⃣ **스레드 풀 사용 (`ExecutorService`)** - 직접 스레드를 생성하면 관리가 어렵기 때문에, **스레드 풀을 사용하여 성능 최적화** - `submit()`으로 작업을 실행하고, `shutdown()`으로 종료 ### 3️⃣ **결과를 받아야 한다면? (`Callable` & `Future`)** - `Callable`을 사용하면 작업이 끝난 후 결과 값을 반환 가능 - `future.get()`을 호출하면 결과를 가져올 수 있음 ### 4️⃣ **공유 자원 충돌 방지 (`ReentrantLock`, `synchronized`)** - `synchronized` 키워드는 단순하지만 유연성이 낮음 - `ReentrantLock`은 더 정교한 동기화 제공 ### 5️⃣ **특정 조건을 만족할 때 실행 (`CountDownLatch`, `CyclicBarrier`)** - `CountDownLatch` → 여러 개의 스레드가 끝날 때까지 대기 - `CyclicBarrier` → 여러 스레드가 동시에 도달해야 실행 --- ## 3. 정리 ✅ 멀티스레딩을 쉽게 하려면? → `ExecutorService` ✅ 스레드 실행 결과를 받아야 한다면? → `Callable`, `Future` ✅ 여러 스레드가 동시에 공유 자원을 사용하면? → `ReentrantLock`, `synchronized` ✅ 여러 작업이 끝난 후 실행되게 하려면? → `CountDownLatch`, `CyclicBarrier` 즉, **자바 동시성 API를 적절히 활용하면 멀티스레딩을 효율적으로 관리할 수 있다!**