멀티스레딩 및 동시성 질문은 면접관이 Java 기술 인터뷰에서 자주 묻는 질문 중 하나입니다. 여기서 중요한 질문은 대부분 면접 관점에서 나열되어 있지만, 앞으로 직면하게 될 문제에 대처하려면 Java 멀티스레딩에 대한 기본 지식을 확실히 이해해야 합니다.
Java 멀티스레딩 면접 질문
1. 프로세스와 스레드의 차이점은 무엇인가요?
프로세스는 프로그램이나 애플리케이션으로 간주될 수 있는 독립적(자체 포함) 실행 환경입니다. 스레드는 프로세스에서 실행되는 작업입니다. Java 런타임 환경은 다양한 클래스와 프로그램을 포함하는 단일 프로세스입니다. 스레드는 경량 프로세스라고 할 수 있습니다. 스레드는 프로세스를 생성하고 상주하는 데 더 적은 리소스가 필요하며 프로세스 내에서 리소스를 공유할 수 있습니다.
2. 멀티스레드 프로그래밍의 장점은 무엇인가요?
멀티 스레드 프로그램에서는 프로그램 효율성을 높이기 위해 여러 스레드가 동시에 실행됩니다. 스레드는 리소스를 기다려야 하기 때문에 CPU는 유휴 상태에 들어가지 않습니다. 여러 스레드가 힙 메모리를 공유하므로 여러 프로세스를 만드는 것보다 일부 작업을 수행하기 위해 여러 스레드를 만드는 것이 더 좋습니다. 예를 들어, 서블릿은 멀티스레딩을 지원하지만 CGI는 지원하지 않기 때문에 서블릿은 CGI보다 낫습니다.
3. 사용자 스레드와 데몬 스레드의 차이점은 무엇인가요?
Java 프로그램에서 스레드를 생성하는 경우 이를 사용자 스레드라고 합니다. 데몬 스레드는 백그라운드에서 실행되며 JVM이 종료되는 것을 방지하지 않는 스레드입니다. 실행 중인 사용자 스레드가 없으면 JVM은 프로그램을 닫고 종료합니다. 데몬 스레드에 의해 생성된 하위 스레드는 여전히 데몬 스레드입니다.
4. 스레드는 어떻게 생성하나요?
스레드를 생성하는 방법에는 두 가지가 있습니다. 하나는 Runnable 인터페이스를 구현한 다음 이를 Thread 생성자에 전달하여 Thread 객체를 생성하는 것이고, 다른 하나는 Thread 클래스를 직접 상속하는 것입니다. 더 알고 싶다면 Java에서 스레드를 생성하는 방법에 대한 이 기사를 읽어보세요.
5. 스레드 수명주기에는 어떤 것이 있나요?
Java 프로그램에서 새 스레드를 생성하면 해당 스레드의 상태는 New입니다. 스레드의 start() 메서드를 호출하면 상태가 Runnable로 변경됩니다. 스레드 스케줄러는 Runnable 스레드 풀의 스레드에 CPU 시간을 할당하고 상태를 실행 중으로 변경합니다. 다른 스레드 상태에는 대기 중, 차단됨, 작동 불능 등이 있습니다. 스레드 수명 주기에 대해 자세히 알아보려면 이 문서를 읽어보세요.
6. Thread 클래스의 run() 메소드를 직접 호출할 수 있나요?
물론이지만 Thread의 run() 메서드를 호출하면 일반 메서드처럼 동작합니다. 새 스레드에서 코드를 실행하려면 Thread.start() 메서드를 사용해야 합니다.
7. 실행 중인 스레드를 일정 시간 동안 일시 중지하는 방법은 무엇입니까?
Thread 클래스의 Sleep() 메서드를 사용하여 일정 시간 동안 스레드를 일시 중지할 수 있습니다. 스레드가 절전 모드에서 해제되면 스레드 상태가 Runnable로 변경되고 스레드 일정에 따라 실행됩니다.
8. 스레드 우선순위에 대해 어떻게 이해하고 있나요?
각 스레드에는 우선순위가 있습니다. 일반적으로 우선순위가 높은 스레드는 실행 시 우선순위를 갖지만 이는 운영 체제와 관련된 스레드 스케줄링 구현에 따라 다릅니다. 스레드의 우선순위를 정의할 수 있지만 이는 우선순위가 높은 스레드가 우선순위가 낮은 스레드보다 먼저 실행된다는 것을 보장하지 않습니다. 스레드 우선순위는 int 변수(1-10)입니다. 1은 가장 낮은 우선순위를 나타내고 10은 가장 높은 우선순위를 나타냅니다.
9. 스레드 스케줄러와 타임 슬라이싱이란 무엇입니까?
스레드 스케줄러는 Runnable 상태의 스레드에 CPU 시간을 할당하는 역할을 하는 운영 체제 서비스입니다. 스레드를 생성하고 시작하면 스레드 실행은 스레드 스케줄러의 구현에 따라 달라집니다. 시간 분할은 사용 가능한 Runnable 스레드에 사용 가능한 CPU 시간을 할당하는 프로세스를 나타냅니다. CPU 시간 할당은 스레드 우선순위 또는 스레드가 대기한 기간을 기반으로 할 수 있습니다. 스레드 스케줄링은 JVM(Java Virtual Machine)에 의해 제어되지 않으므로 애플리케이션이 이를 제어하는 것이 더 좋습니다(즉, 프로그램을 스레드 우선순위에 종속시키지 마십시오).
10. 멀티스레딩에서 컨텍스트 스위칭이란?
컨텍스트 전환은 CPU 상태를 저장하고 복원하는 프로세스로, 스레드 실행이 중단된 지점부터 실행을 재개할 수 있도록 합니다. 컨텍스트 전환은 멀티태스킹 운영 체제 및 멀티스레드 환경의 필수 기능입니다.
11. main() 메소드가 있는 스레드가 Java 프로그램에서 끝나는 마지막 스레드인지 어떻게 확인합니까?
Thread 클래스의 Joint() 메서드를 사용하면 프로그램에서 생성된 모든 스레드가 main() 메서드가 종료되기 전에 종료되도록 할 수 있습니다. 다음은 Thread 클래스의 Joint() 메소드에 대한 기사입니다.
12. 스레드는 어떻게 서로 통신하나요?
스레드가 리소스를 공유할 수 있는 경우 스레드 간 통신은 리소스를 조정하는 중요한 수단입니다. Object 클래스의 wait()notify()notifyAll() 메서드를 사용하면 스레드 간에 리소스 잠금 상태에 대해 통신할 수 있습니다. 스레드 대기, 통지 및 통지All에 대해 자세히 알아보려면 여기를 클릭하십시오.
13. 스레드 통신 메소드 wait(), inform() 및 informAll()이 Object 클래스에 정의된 이유는 무엇입니까?
Java의 모든 객체에는 잠금(모니터, 모니터일 수도 있음)이 있으며, wait(), inform() 및 기타 메소드를 사용하여 객체의 잠금을 기다리거나 모니터가 다른 스레드에 알립니다. 객체의 사용 가능합니다. Java 스레드의 개체에 사용할 수 있는 잠금이나 동기화 장치는 없습니다. 이것이 바로 이러한 메소드가 Object 클래스의 일부인 이유이며 Java의 모든 클래스에는 스레드 간 통신을 위한 기본 메소드가 있습니다
14. wait(), inform() 및 informAll()을 사용해야 하는 이유 동기화된 메소드 아니면 동기화된 블록에서 호출됩니까?
스레드가 개체의 wait() 메서드를 호출해야 하는 경우 스레드는 개체 잠금을 소유해야 합니다. 그런 다음 개체 잠금을 해제하고 다른 스레드가 해당 개체에 대한 inform() 메서드를 호출할 때까지 대기 상태로 들어갑니다. 개체. 마찬가지로, 스레드가 객체의 inform() 메서드를 호출해야 하는 경우 다른 대기 스레드가 객체 잠금을 얻을 수 있도록 객체의 잠금을 해제합니다. 이러한 모든 메서드는 동기화를 통해서만 달성할 수 있는 개체 잠금을 유지하기 위해 스레드를 필요로 하기 때문에 동기화된 메서드나 동기화된 블록에서만 호출할 수 있습니다.
15. Thread 클래스의 sleep()과 Yield() 메소드는 왜 정적인가요?
Thread 클래스의 sleep() 및 Yield() 메서드는 현재 실행 중인 스레드에서 실행됩니다. 따라서 대기 중인 다른 스레드에서 이러한 메서드를 호출하는 것은 의미가 없습니다. 이것이 바로 이러한 메서드가 정적인 이유입니다. 이는 현재 실행 중인 스레드에서 작업할 수 있으며 프로그래머가 이러한 메서드가 실행되지 않는 다른 스레드에서 호출될 수 있다고 잘못 생각하는 것을 방지할 수 있습니다.
16. 스레드 안전성을 확보하는 방법은 무엇입니까?
Java에서 스레드 안전성을 보장하는 방법에는 동기화, 원자 동시 클래스 사용, 동시 잠금 구현, 휘발성 키워드 사용, 불변 클래스 및 스레드 안전 클래스 사용 등 여러 가지 방법이 있습니다. 스레드 안전 튜토리얼에서 자세히 알아볼 수 있습니다.
17. Java에서 휘발성 키워드의 역할은 무엇인가요?
휘발성 키워드를 사용하여 변수를 수정하면 스레드는 변수를 캐시하지 않고 직접 읽습니다. 이렇게 하면 스레드가 읽은 변수가 메모리에 있는 변수와 일치하게 됩니다.
18. 동기화 방법과 동기화 블록 중 어느 것이 더 나은 선택입니까?
동기화된 블록은 전체 개체를 잠그지 않기 때문에 더 나은 선택입니다(물론 전체 개체를 잠그도록 만들 수도 있습니다). 동기화된 메서드는 클래스에 관련되지 않은 동기화된 블록이 여러 개 있는 경우에도 전체 개체를 잠급니다. 이로 인해 일반적으로 해당 블록의 실행이 중지되고 개체에 대한 잠금을 획득할 때까지 기다려야 합니다.
19. 데몬 스레드는 어떻게 생성하나요?
Thread 클래스의 setDaemon(true) 메서드를 사용하여 스레드를 데몬 스레드로 설정합니다. start() 메서드를 호출하기 전에 이 메서드를 호출해야 합니다. 그렇지 않으면 IllegalThreadStateException이 발생합니다. 던져졌다.
20. ThreadLocal이란 무엇입니까?
ThreadLocal은 스레드의 로컬 변수를 생성하는 데 사용됩니다. 우리는 객체의 모든 스레드가 전역 변수를 공유하므로 이러한 변수는 스레드로부터 안전하지 않다는 것을 알고 있습니다. .우리는 동기식 기술을 사용할 수 있습니다. 그러나 동기화를 사용하지 않으려면 ThreadLocal 변수를 선택할 수 있습니다.
각 스레드에는 자체 Thread 변수가 있으며 get()set() 메서드를 사용하여 기본값을 가져오거나 스레드 내에서 값을 변경할 수 있습니다. ThreadLocal 인스턴스는 일반적으로 연결된 스레드 상태가 비공개 정적 속성이기를 원합니다. ThreadLocal 예제 기사에서 ThreadLocal에 대한 작은 프로그램을 볼 수 있습니다.
21. 쓰레드그룹이란? 왜 그것을 사용하는 것이 권장됩니까?
ThreadGroup은 스레드 그룹에 대한 정보를 제공하는 것이 목적인 클래스입니다.
ThreadGroup API는 상대적으로 약하고 Thread보다 더 많은 기능을 제공하지 않습니다. 여기에는 두 가지 주요 기능이 있습니다. 하나는 스레드 그룹의 활성 스레드 목록을 얻는 것이고, 다른 하나는 스레드에 대해 포착되지 않은 예외 핸들러(ncaught 예외 핸들러)를 설정하는 것입니다. 그러나 Java 1.5에서는 Thread 클래스에 setUncaughtExceptionHandler(UncaughtExceptionHandler eh) 메서드도 추가되었으므로 ThreadGroup은 더 이상 사용되지 않으며 계속 사용하지 않는 것이 좋습니다.
t1.setUncaughtExceptionHandler(new UncaughtExceptionHandler(){ @Override public void uncaughtException(Thread t, Throwable e) { System.out.println("exception occured:"+e.getMessage()); } });
22. 자바 스레드 덤프(Thread Dump)란 무엇이며 어떻게 구하나요?
스레드 덤프는 JVM 활성 스레드 목록으로, 시스템 병목 현상과 교착 상태를 분석하는 데 매우 유용합니다. 스레드 덤프를 얻는 방법에는 Profiler, Kill -3 명령, jstack 도구 등을 사용하는 여러 가지 방법이 있습니다. 나는 사용하기 쉽고 JDK와 함께 제공되는 jstack 도구를 선호합니다. 터미널 기반 도구이므로 분석을 위해 스레드 덤프를 주기적으로 생성하는 일부 스크립트를 작성할 수 있습니다. 스레드 덤프 생성에 대해 자세히 알아보려면 이 문서를 읽어보세요.
23. 교착상태란 무엇인가요? 교착상태를 분석하고 방지하는 방법은 무엇입니까?
교착 상태는 2개 이상의 스레드가 영원히 차단되는 상황을 의미합니다. 이 상황에는 최소 2개 이상의 스레드와 2개 이상의 리소스가 필요합니다.
교착 상태를 분석하려면 Java 애플리케이션의 스레드 덤프를 살펴봐야 합니다. BLOCKED 상태에 있는 스레드와 그들이 기다리고 있는 리소스를 찾아야 합니다. 각 리소스에는 고유한 ID가 있으며, 이 ID를 사용하면 이미 개체 잠금을 소유한 스레드를 찾을 수 있습니다.
중첩된 잠금을 피하고, 필요한 경우에만 잠금을 사용하고, 무기한 대기를 피하는 것은 교착 상태를 분석하는 방법을 알아보는 일반적인 방법입니다.
24. Java Timer 클래스란 무엇인가요? 특정 시간 간격으로 작업을 생성하는 방법은 무엇입니까?
java.util.Timer는 미래의 특정 시간에 스레드가 실행되도록 예약하는 데 사용할 수 있는 도구 클래스입니다. Timer 클래스는 일회성 작업이나 정기 작업을 예약하는 데 사용할 수 있습니다.
java.util.TimerTask는 Runnable 인터페이스를 구현하는 추상 클래스입니다. 자체 예약 작업을 생성하고 Timer를 사용하여 실행을 예약하려면 이 클래스를 상속해야 합니다.
다음은 Java Timer의 예입니다.
25. 쓰레드풀이란? Java 스레드 풀을 만드는 방법은 무엇입니까?
스레드 풀은 작업자 스레드 그룹을 관리하며, 실행 대기 중인 작업을 배치하기 위한 대기열도 포함합니다.
java.util.concurrent.Executors는 스레드 풀 생성을 위한 java.util.concurrent.Executor 인터페이스 구현을 제공합니다. 스레드 풀 예제에서는 스레드 풀을 생성 및 사용하는 방법을 보여주거나 ScheduledThreadPoolExecutor 예제를 읽어 주기적 작업을 생성하는 방법을 알아보세요.
Java 동시성 면접 질문
1. 원자 연산이란 무엇인가요? Java Concurrency API의 원자 클래스는 무엇입니까?
원자 연산이란 다른 연산의 영향을 받지 않는 연산 작업 단위를 말합니다. 원자적 작업은 다중 스레드 환경에서 데이터 불일치를 방지하는 데 필요한 수단입니다.
int++는 원자 연산이 아니므로 한 스레드가 해당 값을 읽고 1을 추가하면 다른 스레드가 이전 값을 읽을 수 있으며 이로 인해 오류가 발생할 수 있습니다.
이 문제를 해결하려면 추가 작업이 원자성인지 확인해야 합니다. JDK1.5 이전에는 동기화 기술을 사용하여 이를 수행할 수 있었습니다. JDK 1.5부터 java.util.concurrent.atomic 패키지는 작업이 원자적이고 동기화를 사용할 필요가 없음을 자동으로 보장하는 int 및 long 유형 로딩 클래스를 제공합니다. 이 기사를 읽고 Java의 원자 클래스에 대해 알아볼 수 있습니다.
2. Java Concurrency API의 Lock 인터페이스란 무엇인가요? 동기화에 비해 장점은 무엇입니까?
Lock 인터페이스는 동기화된 메소드 및 동기화된 블록보다 더 확장 가능한 잠금 작업을 제공합니다. 완전히 다른 속성을 가질 수 있는 보다 유연한 구조를 허용하고 조건부 개체의 여러 관련 클래스를 지원할 수 있습니다.
장점은 다음과 같습니다.
잠금을 더 공평하게 만들 수 있습니다.
스레드가 잠금을 기다리는 동안 인터럽트에 응답하도록 할 수 있습니다.
스레드가 잠금을 획득하려고 하도록 할 수 있습니다. 잠금을 획득할 수 없으면 즉시 반환하거나 일정 시간 동안 기다려야 합니다
다양한 범위와 순서로 잠금을 획득하고 해제할 수 있습니다
잠금의 예 더 보기
3. Executors 프레임워크란 무엇인가요?
Executor 프레임워크와 java.util.concurrent.Executor 인터페이스는 Java 5에서 도입되었습니다. Executor 프레임워크는 일련의 실행 전략에 따라 호출, 예약, 실행 및 제어되는 비동기 작업을 위한 프레임워크입니다.
무제한 스레드 생성으로 인해 애플리케이션 메모리 오버플로가 발생할 수 있습니다. 따라서 스레드 수를 제한할 수 있고 이러한 스레드를 재활용하고 재사용할 수 있으므로 스레드 풀을 만드는 것이 더 나은 솔루션입니다. Executors 프레임워크를 사용하여 스레드 풀을 생성하는 것은 매우 편리합니다. Executor 프레임워크를 사용하여 스레드 풀을 생성하는 방법을 알아보려면 이 문서를 읽어보세요.
4. 블로킹 큐란 무엇인가요? 생산자-소비자 모델을 구현하기 위해 차단 대기열을 사용하는 방법은 무엇입니까?
java.util.concurrent.BlockingQueue의 특징은 대기열이 비어 있으면 대기열에서 요소를 가져오거나 삭제하는 작업이 차단되고, 대기열이 가득 차면 대기열에 요소를 추가하는 것입니다. 작업이 차단됩니다.
차단 대기열은 null 값을 허용하지 않습니다. 대기열에 null 값을 추가하려고 하면 NullPointerException이 발생합니다.
차단 대기열의 구현은 스레드로부터 안전하며 모든 쿼리 메서드는 원자적이며 내부 잠금 또는 다른 형태의 동시성 제어를 사용합니다.
BlockingQueue 인터페이스는 Java 컬렉션 프레임워크의 일부로 주로 생산자-소비자 문제를 구현하는 데 사용됩니다.
이 기사를 읽고 차단 대기열을 사용하여 생산자-소비자 문제를 구현하는 방법을 알아보세요.
5. Callable과 Future는 무엇입니까?
Java 5에서는 동시성 패키지에 java.util.concurrent.Callable 인터페이스를 도입했습니다. 이는 Runnable 인터페이스와 매우 유사하지만 반환할 수 있습니다. 또는 예외를 발생시킵니다.
Callable 인터페이스는 제네릭을 사용하여 반환 유형을 정의합니다. Executors 클래스는 스레드 풀의 Callables 내에서 작업을 실행하는 데 유용한 몇 가지 메서드를 제공합니다. Callable 작업은 병렬이므로 반환되는 결과를 기다려야 합니다. java.util.concurrent.Future 객체는 이 문제를 해결합니다. 스레드 풀이 Callable 작업을 제출한 후 Future 객체가 반환됩니다. 이를 사용하면 Callable 작업의 상태를 알 수 있고 Callable이 반환한 실행 결과를 얻을 수 있습니다. Future는 Callable이 종료될 때까지 기다렸다가 실행 결과를 얻을 수 있도록 get() 메서드를 제공합니다.
Callable 및 Future 예제에 대해 자세히 알아보려면 이 기사를 읽어보세요.
6. FutureTask는 무엇인가요?
FutureTask는 비동기 작업을 처리하기 위해 Executor와 함께 사용할 수 있습니다. 일반적으로 FutureTask 클래스를 사용할 필요는 없지만 Future 인터페이스의 일부 메서드를 재정의하고 원래의 기본 구현을 유지하려는 경우 매우 유용합니다. 우리는 그것을 상속하고 필요한 메서드를 재정의할 수 있습니다. Java FutureTask 예제를 읽고 사용 방법을 알아보세요.
7. 동시 컨테이너 구현이란 무엇입니까?
Java 컬렉션 클래스는 오류가 발생하지 않습니다. 즉, 컬렉션이 변경되고 스레드가 반복자를 사용하여 컬렉션을 순회하는 경우 반복자의 next() 메서드가 ConcurrentModificationException 예외를 발생시킵니다.
동시 컨테이너는 동시 순회 및 동시 업데이트를 지원합니다.
주요 클래스는 ConcurrentHashMap, CopyOnWriteArrayList 및 CopyOnWriteArraySet입니다. ConcurrentModificationException을 방지하는 방법을 알아보려면 이 문서를 읽어보세요.
8. Executors 클래스란 무엇인가요?
실행자는 Executor, ExecutorService, ScheduledExecutorService, ThreadFactory 및 Callable 클래스에 대한 몇 가지 도구 메서드를 제공합니다.
실행자를 사용하여 스레드 풀을 쉽게 생성할 수 있습니다.