java

Java 멀티스레딩 인터뷰를 준비하려면 동시성 개념과 실제 경험에 대한 깊은 이해가 필요합니다. 아래에서는 기본 정의부터 가상 스레드 및 구조적 동시성과 같은 고급 주제까지 모든 것을 다루는 신중하게 작성된 40개의 질문과 전문가의 답변을 찾을 수 있습니다.
👉 무료 PDF 다운로드:Java 멀티스레딩 인터뷰 질문 및 답변
멀티스레딩을 사용하면 Java 애플리케이션이 여러 스레드를 동시에 실행하여 CPU 활용도를 최대화하고 응답성을 향상시킬 수 있습니다. 이는 한 스레드가 차단되고 다른 스레드는 계속 처리될 수 있는 I/O 바인딩 작업, 대규모 계산 및 GUI 업데이트에 특히 유용합니다.
예 :웹 서버는 각 요청을 별도의 스레드에 할당하여 수십 개의 클라이언트 요청을 동시에 처리할 수 있으므로 I/O 작업이 차단되는 것을 방지할 수 있습니다.
Java 스레드는 다음 상태를 통해 진행됩니다.
| 상태 | 설명 |
|---|---|
| 신규 | 스레드가 생성되었지만 아직 시작되지 않았습니다. |
| 실행 가능 | 스레드가 실행 준비가 되었거나 현재 실행 중입니다. |
| 차단됨 | 스레드가 모니터 잠금을 기다립니다. |
| 대기 중 | 스레드는 다른 스레드의 신호를 무기한 기다립니다. |
| 시간 초과 | 스레드는 지정된 기간 동안 기다립니다. |
| 해지됨 | 스레드 실행이 완료되었습니다. |
t.start()일 때 호출되면 스레드가 New에서 이동합니다. 실행 가능 .
| 기준 | 프로세스 | 스레드 |
|---|---|---|
| 메모리 | 자신의 주소 공간 | 프로세스 메모리 공유 |
| 커뮤니케이션 | IPC 필요 | 메모리를 직접 공유 |
| 제작 비용 | 비싸다 | 경량 |
| 실패 영향 | 격리 | 형제자매에게 영향을 미칠 수 있음 |
예를 들어 브라우저 프로세스에는 렌더링, 네트워킹 및 사용자 상호 작용을 위한 여러 스레드가 포함될 수 있습니다.
동기화는 한 번에 하나의 스레드만 공유 리소스에 액세스하도록 보장하여 경쟁 조건과 데이터 손상을 방지합니다. synchronized 키워드는 전체 메소드 또는 특정 블록을 잠급니다.
synchronized void increment() {
count++;
}
Thread 연장 class MyThread extends Thread {
public void run() { System.out.println("Thread running"); }
}
new MyThread().start(); Runnable 구현 class MyRunnable implements Runnable {
public void run() { System.out.println("Runnable running"); }
}
new Thread(new MyRunnable()).start(); Callabletask = () -> 42; Future result = executor.submit(task); System.out.println(result.get());
start()의 차이점은 무엇인가요? 그리고 run() ?| 측면 | start() | run() |
|---|---|---|
| 스레드 생성 | 새 OS 스레드 생성 | 현재 스레드에서 실행 |
| 호출 | JVM의 스레드 예약 | 간단한 메소드 호출 |
| 동시성 | 비동기 실행 | 순차 실행 |
t.start()에 전화 걸기 새 스레드를 시작합니다. t.run() 다른 방법처럼 작동합니다.
스레드 안전성은 공유 데이터에 대한 동시 액세스로 인해 상태가 손상되지 않도록 보장합니다. 다음을 통해 달성할 수 있습니다:
synchronized 블록 또는 메소드volatile 변수ReentrantLock , ReadWriteLock )ConcurrentHashMap , CopyOnWriteArrayList )AtomicInteger , AtomicBoolean )AtomicInteger counter = new AtomicInteger(); counter.incrementAndGet();
wait()의 차이점은 무엇인가요? , sleep() 및 yield() ?| 방법 | 수업 | 잠금 해제 | 목적 | 기간 |
|---|---|---|---|---|
wait() | 객체 | 예 | 알림을 기다리세요 | 통지시까지 |
sleep() | 스레드 | 아니요 | 실행 일시중지 | 고정 시간 |
yield() | 스레드 | 아니요 | 스케줄러 전환 제안 | 예측 불가능 |
wait() 사용 스레드 간 통신용 sleep()을 사용하세요 스레드를 일시 중지합니다.
프레임워크는 스레드 생성에서 작업 제출을 분리하여 효율적인 스레드 풀링 및 리소스 재사용을 가능하게 합니다. java.util.concurrent의 일부입니다. 그리고 다음을 제공합니다:
ExecutorService executor = Executors.newFixedThreadPool(5);
executor.submit(() -> System.out.println("Task executed"));
executor.shutdown(); | 풀 유형 | 팩토리 메소드 | 설명 |
|---|---|---|
| FixedThreadPool | newFixedThreadPool(n) | 고정된 스레드 수 |
| 캐시된ThreadPool | newCachedThreadPool() | 필요에 따라 스레드를 생성하고 유휴 스레드를 재사용합니다. |
| 단일스레드 실행자 | newSingleThreadExecutor() | 순차 실행을 위한 단일 작업자 스레드 |
| ScheduledThreadPool | newScheduledThreadPool(n) | 지연되거나 주기적인 작업 지원 |
| 워크스틸링풀 | newWorkStealingPool() | 사용 가능한 프로세서를 동적으로 활용 |
두 개 이상의 스레드가 서로 잠금을 해제할 때까지 무기한 기다릴 때 교착 상태가 발생합니다. 일반적으로 일관되지 않은 잠금 순서로 인해 발생합니다.
synchronized (A) {
synchronized (B) { /*...*/ }
}
synchronized (B) {
synchronized (A) { /*...*/ }
}
예방 전략:
tryLock() 사용 시간 초과가 있습니다.synchronized의 차이점 및 ReentrantLock .| 기능 | synchronized | 재진입 잠금 |
|---|---|---|
| 획득 | 암시적 | lock()를 통해 명시적 |
| 잠금 해제 중 | 메소드 종료 시 자동 | unlock()를 통한 수동 |
| 시도/시간 초과 | 사용할 수 없음 | tryLock() 지원 그리고 시간 초과 |
| 공정성 | 구성할 수 없음 | 공정한 주문을 지지합니다 |
| 조건 변수 | 지원되지 않음 | 여러 Condition 지원 개체 |
ReentrantLock lock = new ReentrantLock();
if (lock.tryLock(1, TimeUnit.SECONDS)) {
try { /* critical section */ } finally { lock.unlock(); }
} volatile의 차이점 그리고 synchronized .| 측면 | 휘발성 | 동기화 |
|---|---|---|
| 목적 | 가시성 | 원자성 + 가시성 |
| 원자성 | 보증 없음 | 보장 |
| 잠금 | 아니요 | 예 |
| 사용 사례 | 간단한 플래그 | 복합 연산 |
volatile boolean running = true;
synchronized void increment() { count++; } ThreadLocal은 스레드별 데이터를 제공하므로 공유 변경 가능 상태가 필요하지 않습니다. 각 스레드는 자체 격리된 복사본에 액세스합니다.
ThreadLocalcounter = ThreadLocal.withInitial(() -> 0); counter.set(counter.get() + 1);
remove()에 전화해야 함 메모리 누수를 방지하기 위해 스레드 풀에서
원자 클래스(예:AtomicInteger , AtomicBoolean , AtomicReference ) CAS(Compare-And-Swap)를 사용하여 잠금이 없고 스레드로부터 안전한 작업을 수행합니다. 동기화된 블록에 비해 간단한 업데이트에 대해 더 높은 처리량을 제공합니다.
AtomicInteger counter = new AtomicInteger(); counter.incrementAndGet();
| 측면 | 세마포어 | 잠금 |
|---|---|---|
| 목적 | 동시 액세스 제한 | 상호 배제 |
| 허가 | 다중 | 싱글 |
| 차단 | 허가 취득 | 소유권 획득 |
| 사용 사례 | 연결 풀링 | 중요 섹션 보호 |
Semaphore sem = new Semaphore(3); sem.acquire(); // use resource sem.release();
Java 7에 도입된 이 기능을 사용하면 작업 도용 알고리즘을 사용하여 재귀적으로 분할 가능한 작업을 병렬 실행할 수 있습니다. 유휴 스레드는 바쁜 스레드의 작업을 훔쳐 CPU 활용도를 극대화합니다.
class SumTask extends RecursiveTask{ protected Integer compute() { if (end - start <= threshold) return computeDirectly(); int mid = (start + end) / 2; SumTask left = new SumTask(start, mid); SumTask right = new SumTask(mid, end); left.fork(); return right.compute() + left.join(); } }
CompletableFuture는 비차단, 구성 가능한 비동기 작업을 허용하여 콜백 지옥을 제거하고 연결, 예외 처리 및 병렬 구성을 지원합니다.
CompletableFuture.supplyAsync(() -> "Hello")
.thenApply(str -> str + " World")
.thenAccept(System.out::println); 데몬 스레드는 백그라운드에서 실행되어 가비지 수집이나 타이머 작업과 같은 서비스를 제공합니다. 사용자 스레드가 남아 있지 않으면 JVM은 모든 데몬 스레드를 자동으로 종료합니다.
Thread daemon = new Thread(() -> System.out.println("Daemon running"));
daemon.setDaemon(true);
daemon.start(); shutdown()를 사용하여 실행 프로그램을 정상적으로 종료합니다. 또는 shutdownNow() .JMM은 스레드가 메모리를 통해 상호 작용하는 방식을 정의하여 가시성, 순서 및 원자성을 보장합니다. 이는 올바른 동시 코드를 작성하는 데 중요한 사전 발생 관계를 설정합니다.
| 기능 | ConcurrentHashMap | 동기화된 지도 |
|---|---|---|
| 잠금 세분성 | 세그먼트 수준(일부) | 전체 지도 |
| 경합 중인 실적 | 높음 | 낮음 |
| Null 키/값 | 허용되지 않음 | 허용 |
| 반복자 일관성 | 약한 일관성 | 빠른 실패 |
| 동시 읽기 | 허용 | 차단됨 |
jstack <pid>을 통한 스레드 덤프 교착상태를 드러냅니다.ThreadMXBean.findDeadlockedThreads()를 사용한 프로그래밍 방식 감지 .병렬 스트림은 내부적으로 Fork/Join 프레임워크를 사용하여 데이터 처리를 위한 고급 API를 제공합니다. 명시적 스레드는 수동 관리가 필요하지만 세밀한 제어 기능을 제공합니다.
| 측면 | 병렬 스트림 | 스레드 |
|---|---|---|
| 추상화 | 고수준 API | 낮은 수준의 제어 |
| 관리 | ForkJoinPool을 통한 자동 | 수동 스레드 풀 |
| 조정 | 공통 풀 사용 | 사용자 정의 풀 크기 |
| 오류 처리 | 제한적 | 모든 권한 |
| 기능 | 카운트다운래치 | 순환장벽 | 페이저 |
|---|---|---|---|
| 재설정 | 아니요 | 예 | 예 |
| 파티 | 수정됨 | 수정됨 | 동적 |
| 사용 사례 | 작업이 완료될 때까지 기다리세요 | 만나야 할 스레드 | 동적 조정 |
CountDownLatch latch = new CountDownLatch(3);
for (...) new Thread(() -> { /* work */ latch.countDown(); }).start();
latch.await(); | 측면 | 실행 가능 | 호출 가능 |
|---|---|---|
| 반환 값 | 아니요 | 예 |
| 확인된 예외 | 아니요 | 예 |
| 패키지 | java.lang | java.util.concurrent |
Callabletask = () -> 42; Future result = executor.submit(task); System.out.println(result.get());
BlockingQueue는 생산자-소비자 패턴을 단순화하는 스레드로부터 안전한 차단 작업을 제공합니다.
BlockingQueuequeue = new ArrayBlockingQueue<>(10); new Thread(() -> queue.put(1)).start(); // Producer new Thread(() -> System.out.println(queue.take())).start(); // Consumer
wait() 제거 /notify() .우선순위가 낮은 스레드가 CPU 시간을 수신하지 못하는 경우 기아 상태가 발생합니다. 라이브록은 스레드가 지속적으로 상태를 변경하지만 진행되지 않을 때 발생합니다. 완화 방법에는 공정한 잠금, 바쁜 대기 방지 및 적절한 일정 관리가 포함됩니다.
결제 게이트웨이에서 동시 거래 처리는 다음을 통해 최적화되었습니다.
결과:처리량이 35% 증가하고 대기 시간이 40% 감소했습니다.
Java 21에 도입된 가상 스레드는 JVM에서 관리하는 경량 스레드로, 최소한의 오버헤드로 수백만 개의 동시 작업을 가능하게 합니다.
| 기능 | 플랫폼 스레드 | 가상 스레드 |
|---|---|---|
| 관리자 | OS | JVM |
| 제작 비용 | 높음 | 매우 낮음 |
| 동시성 수준 | 수천 | 수백만 |
| 일정 | OS 수준 | JVM 협동 |
| 사용 사례 | CPU 바인딩 작업 | I/O 바인딩/고동시 작업 |
Thread.startVirtualThread(() -> System.out.println("Virtual thread running")); Java 21에서 미리 본 구조화된 동시성은 여러 동시 작업을 단일 단위로 처리하여 함께 시작, 관리, 종료되도록 합니다. 고아 스레드를 제거하고 오류 전파를 단순화합니다.
try (var scope = new StructuredTaskScope.ShutdownOnFailure()) {
Future user = scope.fork(() -> findUser());
Future order = scope.fork(() -> fetchOrderCount());
scope.join();
scope.throwIfFailed();
System.out.println(user.resultNow() + " has " + order.resultNow() + " orders.");
} Reactive Streams는 데이터 스트림 처리를 위한 비차단, 역압 인식 모델을 제공하여 Project Reactor, RxJava 및 Spring WebFlux와 같은 프레임워크의 기반을 형성합니다.
Publisher – 데이터를 생성합니다.Subscriber – 데이터를 소비합니다.Subscription – 흐름을 제어합니다.Processor – 게시자와 구독자 모두.Flow.Publisherpublisher = subscriber -> subscriber.onNext(42);
항상 Thread.interrupted()를 확인하세요. 루프에서 InterruptedException를 포착한 후 리소스를 정리하고 인터럽트 상태를 유지합니다. .
while (!Thread.currentThread().isInterrupted()) {
try { Thread.sleep(1000); }
catch (InterruptedException e) {
Thread.currentThread().interrupt(); // restore flag
break;
}
} 동시성은 실행을 인터리브하여 여러 작업을 관리하는 반면, 병렬성은 여러 CPU 코어에서 동시에 작업을 실행합니다.
| 개념 | 정의 | 예 |
|---|---|---|
| 동시성 | 인터리빙 작업 | 1000개의 클라이언트 요청을 동시에 처리 |
| 병렬성 | 동시 실행 | CPU 코어 전체에서 계산 실행 |
| 도구 | 목적 |
|---|---|
| j스택 | 스레드 덤프 캡처 |
| jconsole / VisualVM | 실시간 모니터링 |
| JFR(자바 비행 기록 장치) | 낮은 오버헤드 프로파일링 |
| 미션 제어(JMC) | JFR 녹음 시각화 |
| 비동기 프로파일러 | CPU 및 할당 프로파일링 |
| ThreadMXBean | 프로그래밍 방식 검사 |
ThreadMXBean bean = ManagementFactory.getThreadMXBean(); System.out.println(bean.getThreadCount());
최적화에는 세분화된 잠금, 잠금 없는 구조, 스레드 생성 최소화 및 스레드 로컬 저장소 사용이 포함됩니다.
| 유형 | 정의 | 보증 |
|---|---|---|
| 자물쇠 없는 | 최소 하나의 스레드가 진행됩니다. | 시스템 전체 진행 상황. |
| 대기 시간 없음 | 모든 스레드는 제한된 단계로 진행됩니다. | 가장 강력한 보증 |
| 장애물 없음 | 경합 없이 진행됩니다. | 가장 약한 보증. |
AtomicInteger 작업은 잠금이 없습니다. 차단 대기열은 잠금을 사용합니다.
각 작업자는 자신의 데크를 유지합니다. 유휴 작업자는 다른 작업자의 작업을 도용하여 경합을 줄이고 처리량을 향상시킵니다.
ForkJoinPool pool = new ForkJoinPool(); pool.submit(() -> IntStream.range(0, 100).parallel().forEach(System.out::println));
결과:최소한의 차단과 최적의 리소스 사용으로 수백만 개의 동시 연결을 달성합니다.
다음은 면접관이 기대하는 10가지 현실적인 질문과 세련된 샘플 답변입니다.
응시자는 OS 및 JVM 기본 사항, 메모리 사용량 및 실행 흐름을 설명해야 합니다. 예를 들어, 브라우저 프로세스에는 렌더링, 네트워킹 및 사용자 입력을 위한 여러 스레드가 포함되어 있습니다.
synchronized의 목적 키워드?동시성 제어, 내장 잠금 및 스레드 안전성에 대해 설명합니다. 한 번에 하나의 스레드만 임계 섹션에 액세스하도록 보장합니다.
교착 상태 시나리오, 스레드 덤프를 통해 이를 식별한 방법, 일관된 잠금 순서를 적용하여 해결한 방법을 설명하세요.
관계 이전에 일어난 일을 설명하세요, volatile , 가시성과 순서를 보장하는 동기화 구성.
wait()의 차이점 , notify() 및 notifyAll() ?스레드 간 통신에 대해 설명하고 메커니즘을 모니터링합니다.
잠금 경합을 식별하고 synchronized를 교체하세요. ConcurrentHashMap 사용 , 측정 가능한 처리량 증가를 보여줍니다.
ReentrantLock을 사용하여 스레드로부터 안전한 컬렉션 또는 명시적 잠금을 사용하세요. 세밀한 제어가 가능합니다.
ExecutorService의 역할 ?작업자 스레드 풀을 관리하고 오버헤드를 줄이며 수명 주기 관리를 단순화합니다.
로드 시 재현하고, 로깅을 강화하고, 적절한 동기화를 추가하여 수정하세요.
ThreadPoolExecutor으로 우선순위 대기열 사용 우선순위가 높은 작업을 위한 사용자 정의 비교기
java
Industry 4.0, 또는 일부에서 4차 산업 혁명이라고 부르는 것은 차세대 기술 혁명입니다. 이전의 3대 산업 혁명인 증기/수력, 전기 및 전자를 진행합니다. Industry 4.0은 3차 산업 혁명을 채택하고 확장합니다. 자동화 및 스마트 가능성. 회사가 스마트 제조를 생산에 통합하기 시작하면서 이에 대한 예는 우리 주변에서 찾을 수 있습니다. 그 결과 로봇이 기하급수적으로 공장에 통합되고 있습니다. 또한 공장에서는 사람들과 함께 작업하여 유연성과 효율성을 높일 수 있는 협업 로봇이 증가하고 있으며 산업용 사물 인터넷이 부상
소스 | 핀칸티에리 조선 선두업체인 Fincantieri S.p.A.(이탈리아 트리에스테)는 일본 Teijin Ltd.의 유럽 자회사인 Teijin Automotive Technologies와 해양 선박용 비구조 복합재 격벽을 공동 개발하기 위한 양해각서(MOU)를 체결했습니다. 이번 계약에 따라 Teijin Automotive Technologies는 Fincantieri가 중요한 지원을 제공하면서 엔지니어링 및 산업화 노력을 주도하게 됩니다. 이 계획의 목표는 무게를 줄이고 다양한 기능을 통합하여 현대 해양 선박에 요구되는