>  기사  >  Java  >  수집할 가치가 있는 Java 멀티스레딩 인터뷰 질문(답변 포함)

수집할 가치가 있는 Java 멀티스레딩 인터뷰 질문(답변 포함)

青灯夜游
青灯夜游앞으로
2019-11-25 15:21:582109검색

이 기사에는 Java 멀티스레딩 인터뷰 질문과 답변이 요약되어 있습니다. 도움이 필요한 친구들이 참고할 수 있기를 바랍니다.

수집할 가치가 있는 Java 멀티스레딩 인터뷰 질문(답변 포함)

스레드란 무엇인가요?

스레드는 운영체제가 계산 스케줄링을 수행할 수 있는 가장 작은 단위이며 프로세스에 포함되어 실제 동작하는 단위입니다. 프로그래머는 다중 프로세서 프로그래밍에 이를 사용할 수 있으며, 다중 스레딩을 사용하여 계산 집약적인 작업 속도를 높일 수 있습니다. 예를 들어 하나의 스레드가 작업을 완료하는 데 100밀리초가 걸린다면 10개의 스레드를 사용하여 작업을 완료하는 데는 10밀리초밖에 걸리지 않습니다. Java는 언어 수준에서 탁월한 멀티스레딩 지원을 제공하며 이는 좋은 판매 포인트이기도 합니다.

2) 스레드와 프로세스의 차이점은 무엇인가요?

스레드는 프로세스의 하위 집합입니다. 프로세스에는 여러 스레드가 있을 수 있으며 각 스레드는 서로 다른 작업을 병렬로 수행합니다. 서로 다른 프로세스는 서로 다른 메모리 공간을 사용하며 모든 스레드는 동일한 메모리 공간을 공유합니다. 이것을 스택 메모리와 혼동하지 마십시오. 각 스레드에는 로컬 데이터를 저장하는 자체 스택 메모리가 있습니다.

3) Java에서 스레드를 구현하는 방법은 무엇입니까?

언어레벨에는 두가지 방법이 있습니다. java.lang.Thread 클래스의 인스턴스는 스레드이지만 실행하려면 java.lang.Runnable 인터페이스를 호출해야 합니다. 스레드 클래스 자체가 호출되는 Runnable 인터페이스이므로 java.lang.Thread 클래스를 상속받을 수 있습니다. 또는 Runnable 인터페이스를 직접 호출하여 스레드를 구현하는 run() 메서드를 작성하세요.

4) Runnable을 사용하시나요, 아니면 Thread를 사용하시나요?

이 질문은 이전 질문에 대한 후속 질문입니다. Thread 클래스를 상속하거나 Runnable 인터페이스를 호출하여 스레드를 구현할 수 있다는 것은 누구나 알고 있습니다. 언제 사용되나요? Java가 클래스의 다중 상속을 지원하지 않지만 다중 인터페이스 호출을 허용한다는 사실을 알고 있다면 이 질문에 쉽게 대답할 수 있습니다. 따라서 다른 클래스로부터 상속받고 싶다면 당연히 Runnable 인터페이스를 호출해야 합니다.

6) Thread 클래스의 start() 메소드와 run() 메소드의 차이점은 무엇인가요?

이 질문은 자주 묻는 질문이지만 Java 스레드 모델에 대한 면접관의 이해를 구별할 수 있습니다. start() 메서드는 새로 생성된 스레드를 시작하는 데 사용되며, start()는 내부적으로 run() 메서드를 호출하는데, 이는 run() 메서드를 직접 호출하는 것과는 다른 효과를 갖습니다. run() 메소드를 호출하면 원래 스레드에서만 호출됩니다. 새 스레드가 시작되지 않으면 start() 메소드는 새 스레드를 시작합니다.

7) Java에서 Runnable과 Callable의 차이점은 무엇입니까?

Runnable과 Callable은 모두 서로 다른 스레드에서 실행되는 작업을 나타냅니다. Runnable은 JDK1.0부터 제공되었으며 Callable은 JDK1.5에 추가되었습니다. 이들 사이의 주요 차이점은 Callable의 call() 메소드는 값을 반환하고 예외를 발생시킬 수 있는 반면 Runnable의 run() 메소드에는 이러한 기능이 없다는 것입니다. Callable은 계산 결과가 로드된 Future 객체를 반환할 수 있습니다.

8) Java에서 CyclicBarrier와 CountDownLatch의 차이점은 무엇입니까?

CyclicBarrier와 CountDownLatch는 모두 스레드 그룹이 다른 스레드를 기다리도록 만드는 데 사용될 수 있습니다. CyclicBarrier와 달리 CountdownLatch는 재사용할 수 없습니다.

9) Java 메모리 모델이란 무엇입니까?

Java 메모리 모델은 Java 프로그램이 다양한 메모리 아키텍처, CPU 및 운영 체제에서 결정론적으로 동작하도록 지정하고 안내합니다. 이는 다중 스레드 상황에서 특히 중요합니다. Java 메모리 모델은 한 스레드의 변경 사항이 다른 스레드에 표시될 수 있으며 스레드 간에 우선 순위 관계가 있음을 보장합니다. 이 관계는 프로그래머가 동시에 프로그래밍할 때 더 명확하게 생각할 수 있도록 몇 가지 규칙을 정의합니다. 예를 들어, 미리보기 관계는 다음을 보장합니다.

  • 스레드의 코드가 순서대로 실행될 수 있습니다. 이를 프로그램 순서 규칙이라고 합니다.
  • 동일한 잠금의 경우 나중에 발생하는 다른 잠금 작업 전에 잠금 해제 작업이 발생해야 하며, 이를 모니터 잠금 규칙이라고도 합니다.
  • 이전 휘발성 쓰기 작업은 휘발성 변수 규칙이라고도 하는 다음 휘발성 읽기 작업보다 우선합니다.
  • 스레드 내의 모든 작업은 이 스레드의 start() 호출 이후에 호출되어야 하며, 이는 스레드 시작 규칙이라고도 합니다.
  • 스레드 종료 규칙에 따라 스레드가 종료되기 전에 스레드의 모든 작업이 수행됩니다.
  • 객체의 마무리 작업은 객체가 생성된 후에 완료되어야 하며, 객체 종료 규칙이라고도 합니다.
  • Transportability

Java 메모리 모델에 대한 이해를 심화하려면 "Java 동시 프로그래밍 실습" 16장을 읽어보시길 적극 권장합니다.

10) Java의 휘발성 변수란 무엇입니까?

휘발성은 멤버 변수에서만 사용할 수 있는 특수 수식자입니다. Java 동시 프로그램에 동기화 클래스가 없으면 멤버 변수에 대한 다중 스레드 작업은 다른 스레드에 투명합니다. 휘발성 변수는 이전 쓰기 작업 후에 다음 읽기 작업이 발생하도록 보장할 수 있습니다. 이는 이전 질문의 휘발성 변수 규칙입니다.

11) 스레드 안전성이란 무엇입니까? Vector는 스레드로부터 안전한 클래스인가요?

코드가 있는 프로세스에서 동시에 실행 중인 여러 스레드가 있는 경우 이러한 스레드가 이 코드를 동시에 실행할 수 있습니다. 각 실행의 결과가 단일 스레드 실행의 결과와 동일하고 다른 변수의 값도 예상과 동일하면 스레드로부터 안전합니다. 스레드로부터 안전한 카운터 클래스는 동일한 인스턴스 개체가 여러 스레드에서 사용될 때 계산 오류를 일으키지 않습니다. 분명히 컬렉션 클래스를 스레드로부터 안전하고 스레드로부터 안전하지 않은 두 그룹으로 나눌 수 있습니다. Vector는 동기화된 메서드를 사용하여 스레드 안전성을 달성하는 반면, 이와 유사한 ArrayList는 스레드로부터 안전하지 않습니다.

12) Java의 경쟁 조건이란 무엇입니까? 예를 들어보세요.

Race 조건은 동시 조건에서 프로그램에 일부 버그를 일으킬 수 있습니다. 여러 스레드가 일부 리소스를 놓고 경쟁할 때 경쟁 조건이 발생합니다. 먼저 실행하려는 프로그램이 경쟁에 실패하고 나중에 실행되면 전체 프로그램에 일부 불확실한 버그가 나타납니다. 이러한 버그는 스레드 간의 무작위 경쟁으로 인해 발견 및 재발이 어렵습니다.

13) Java에서 스레드를 중지하는 방법은 무엇입니까?

Java는 풍부한 API를 제공하지만 스레드 중지를 위한 API는 제공하지 않습니다. JDK 1.0에는 원래 stop(), suspens() 및 이력서()와 같은 일부 제어 메서드가 있었지만 잠재적인 교착 상태 위협으로 인해 후속 JDK 버전에서는 더 이상 사용되지 않습니다. 스레드를 중지하는 안전한 방법. run() 또는 call() 메서드가 실행되면 스레드가 자동으로 종료됩니다. 스레드를 수동으로 종료하려면 휘발성 부울 변수를 사용하여 run() 메서드의 루프를 종료하거나 작업을 취소하여 스레드를 중단할 수 있습니다. .

14) 스레드가 실행되는 동안 예외가 발생하면 어떻게 되나요?

이것은 인터뷰에서 만난 매우 까다로운 Java 인터뷰 질문입니다. 간단히 말해서 예외가 포착되지 않으면 스레드 실행이 중지됩니다. Thread.UncaughtExceptionHandler는 포착되지 않은 예외로 인해 발생한 갑작스러운 스레드 중단을 처리하는 데 사용되는 내장 인터페이스입니다. 포착되지 않은 예외로 인해 스레드가 중단되면 JVM은 Thread.getUncaughtExceptionHandler()를 사용하여 스레드의 UncaughtExceptionHandler를 쿼리하고 처리를 위해 핸들러의 uncaughtException() 메서드에 매개변수로 스레드와 예외를 전달합니다.

15) 두 스레드 간에 데이터를 공유하는 방법은 무엇입니까?

공유 객체를 통해 이를 달성하거나 차단 대기열과 같은 동시 데이터 구조를 사용할 수 있습니다. 이 튜토리얼 "Java Inter-Thread Communication"(두 스레드 간의 객체 공유 포함)에서는 대기 및 알림 메서드를 사용하여 생산자-소비자 모델을 구현합니다.

16) Java에서 통지와 통지All의 차이점은 무엇입니까?

여러 스레드가 단일 모니터 잠금을 기다릴 수 있기 때문에 이는 또 다른 까다로운 질문입니다. Java API 설계자는 대기 조건이 변경될 때 이를 알리는 몇 가지 메서드를 제공하지만 이러한 메서드는 완전히 구현되지 않습니다. 통지() 메소드는 특정 스레드를 깨울 수 없으므로 스레드가 대기 중인 경우에만 유용합니다. 그리고 informAll()은 모든 스레드를 깨우고 적어도 하나의 스레드가 계속 실행될 수 있도록 잠금을 위해 경쟁할 수 있도록 합니다.

17) 스레드 클래스에 wait, inform 및 informAll 메소드가 없는 이유는 무엇입니까?

기존 시스템에 대한 면접관의 견해와 일반적이지만 불합리해 보이는 몇 가지 사항을 조사하는 디자인 관련 질문입니다. 이러한 질문에 대답할 때 이러한 메서드를 Object 클래스에 넣는 것이 왜 타당하고, Thread 클래스에 넣지 않는 이유를 설명해야 합니다. 분명한 이유는 JAVA에서 제공하는 잠금이 스레드 수준이 아닌 개체 수준에 있기 때문입니다. 각 개체에는 잠금이 있으며 스레드를 통해 획득됩니다. 스레드가 일부 잠금을 기다려야 하는 경우 개체에서 wait() 메서드를 호출하는 것이 좋습니다. wait() 메서드가 Thread 클래스에 정의되어 있으면 스레드가 어떤 잠금을 기다리고 있는지 명확하지 않습니다. 간단히 말해서 wait, inform 및 informAll은 잠금 수준 작업이므로 잠금은 개체에 속하므로 Object 클래스에 정의됩니다.

18) ThreadLocal 변수란 무엇인가요?

ThreadLocal은 Java의 특수 변수입니다. 각 스레드에는 ThreadLocal이 있습니다. 즉, 각 스레드에는 자체 독립 변수가 있으며 경쟁 조건이 완전히 제거됩니다. 생성 비용이 많이 드는 개체에 대해 스레드 안전성을 확보하는 좋은 방법입니다. 예를 들어 ThreadLocal을 사용하여 SimpleDateFormat 스레드를 안전하게 만들 수 있습니다. 해당 클래스는 생성 비용이 많이 들고 호출마다 다른 인스턴스를 생성해야 하므로 사용할 가치가 없기 때문입니다. 로컬 범위 이를 사용하여 각 스레드에 고유한 변수 복사본이 제공되면 효율성이 크게 향상됩니다. 첫째, 재사용을 통해 생성되는 고가의 객체 수가 줄어듭니다. 둘째, 비용이 많이 드는 동기화나 불변성을 사용하지 않고도 스레드 안전성을 얻을 수 있습니다. 스레드 로컬 변수의 또 다른 좋은 예는 다중 스레드 환경에서 생성하기 위해 비용이 많이 드는 Random 개체의 수를 줄이는 ThreadLocalRandom 클래스입니다.

19) FutureTask란 무엇인가요?

Java 동시 프로그램에서 FutureTask는 취소할 수 있는 비동기 작업을 나타냅니다. 작업 시작 및 취소, 작업 완료 여부 쿼리, 작업 결과 검색 등의 메서드가 있습니다. 작업이 완료된 경우에만 결과를 검색할 수 있습니다. 작업이 완료되지 않은 경우 get 메서드가 차단됩니다. FutureTask 객체는 Callable 및 Runnable을 호출하는 객체를 래핑할 수 있습니다. FutureTask는 Runnable 인터페이스도 호출하므로 실행을 위해 Executor에 제출할 수 있습니다.

20) Java에서 Interrupted 메소드와 isInterruptedd 메소드의 차이점은 무엇입니까?

interrupted()와 isInterrupted()의 주요 차이점은 전자는 인터럽트 상태를 지우고 후자는 그렇지 않다는 것입니다. Java 멀티스레딩의 인터럽트 메커니즘은 내부 플래그를 사용하여 구현됩니다. 스레드를 인터럽트하기 위해 Thread.interrupt()를 호출하면 인터럽트 플래그가 true로 설정됩니다. 인터럽트 스레드가 인터럽트 상태를 확인하기 위해 정적 메서드 Thread.interrupted()를 호출하면 인터럽트 상태가 지워집니다. 비정적 메서드 isInterrupted()는 다른 스레드의 인터럽트 상태를 쿼리하는 데 사용되며 인터럽트 상태 식별자를 변경하지 않습니다. 간단히 말해서 InterruptedException을 발생시키는 모든 메소드는 인터럽트 상태를 지웁니다. 어떤 경우든 스레드의 인터럽트 상태는 인터럽트를 호출하는 다른 스레드에 의해 변경될 수 있습니다.

21) 동기화된 블록에서 대기 및 알림 메소드가 호출되는 이유는 무엇입니까?

주로 Java API에서 이를 요구하기 때문에 이를 수행하지 않으면 코드에서 IllegalMonitorStateException이 발생합니다. 또 다른 이유는 대기와 알림 사이의 경쟁 조건을 피하기 위해서입니다.

22) 루프에서 대기 조건을 확인해야 하는 이유는 무엇입니까?

대기 상태에 있는 스레드는 잘못된 경보와 가짜 깨우기를 받을 수 있습니다. 루프에서 대기 조건을 확인하지 않으면 프로그램이 종료됩니다. 종료 조건이 충족되지 않은 경우 종료됩니다. 따라서 대기 중인 스레드가 깨어날 때 원래 대기 상태는 여전히 유효한 것으로 간주할 수 없습니다. 통지() 메서드가 호출된 후 대기 중인 스레드가 깨어나기 전에 변경될 수 있습니다. 이것이 루프에서 wait() 메소드를 사용하는 것이 더 효과적인 이유입니다. Eclipse에서 wait를 호출하고 이를 시도하도록 알리는 템플릿을 만들 수 있습니다. 이 문제에 대해 더 자세히 알아보려면 "Effective Java" 책의 스레드 및 동기화 장을 읽어 보시기 바랍니다.

23) Java에서 동기화된 컬렉션과 동시 컬렉션의 차이점은 무엇인가요?

동기화 컬렉션과 동시 컬렉션 모두 멀티스레딩과 동시성에 적합한 스레드로부터 안전한 컬렉션을 제공하지만 동시 컬렉션은 확장성이 더 뛰어납니다. Java 1.5 이전에는 프로그래머가 동기화된 컬렉션만 사용할 수 있었으며 이로 인해 다중 스레드 동시성 중에 경합이 발생하고 시스템 확장성이 저하되었습니다. Java 5에서는 스레드 안전성을 제공할 뿐만 아니라 잠금 분리 및 내부 파티셔닝과 같은 최신 기술을 통해 확장성을 향상시키는 ConcurrentHashMap과 같은 동시 컬렉션을 도입했습니다.

24) Java에서 힙과 스택의 차이점은 무엇입니까?

이 질문이 멀티스레딩 및 동시성 면접 질문으로 분류되는 이유는 무엇인가요? 스택은 스레드와 밀접한 메모리 영역이기 때문입니다. 각 스레드에는 로컬 변수, 메서드 매개변수 및 스택 호출을 저장하는 데 사용되는 자체 스택 메모리가 있습니다. 힙은 모든 스레드가 공유하는 공통 메모리 영역입니다. 객체는 모두 힙에 생성되며 효율성을 높이기 위해 스레드는 이를 힙에서 자체 스택으로 캐시합니다. 이 변수를 여러 스레드에서 사용하면 이때 휘발성 변수가 작동할 수 있습니다. 스레드가 메인 스택에서 시작되어야 합니다. 메모리에서 변수 값을 읽어야 합니다.

25) 스레드 풀이란 무엇인가요? 왜 그것을 사용합니까?

스레드를 생성하려면 리소스와 시간이 많이 소요됩니다. 작업이 올 때만 스레드를 생성하면 응답 시간이 길어지고 프로세스에서 생성할 수 있는 스레드 수가 제한됩니다. 이러한 문제를 방지하기 위해 프로그램이 시작될 때 처리에 응답하기 위해 여러 스레드가 생성되며 이를 스레드 풀이라고 하며 내부 스레드를 작업자 스레드라고 합니다. JDK1.5부터 Java API는 다양한 스레드 풀을 생성할 수 있도록 Executor 프레임워크를 제공합니다. 예를 들어 단일 스레드 풀은 고정된 수의 스레드 풀 또는 캐시 스레드 풀(단기 작업이 많은 프로그램에 적합한 확장 가능한 스레드 풀)을 한 번에 하나의 작업을 처리합니다.

26) 생산자-소비자 문제를 해결하기 위한 코드는 어떻게 작성하나요?

실제로 해결하는 스레딩 문제 중 다수는 하나의 스레드가 다른 스레드가 사용할 작업을 생성하는 생산자-소비자 모델에 속합니다. 이 문제를 해결하려면 스레드 간에 통신하는 방법을 알아야 합니다. 더 낮은 수준의 방법은 대기 및 알림을 사용하여 이 문제를 해결하는 것입니다. 더 나은 방법은 Semaphore 또는 BlockingQueue를 사용하여 생산자-소비자 모델을 구현하는 것입니다.

27) 교착상태를 피하는 방법은 무엇입니까?


Java 멀티스레딩의 교착 상태
Deadlock은 실행 중 둘 이상의 프로세스 간의 경합으로 인해 발생하는 상호 대기 현상을 나타냅니다. 외부의 힘이 없으면 발전할 수 없습니다. 교착 상태로 인해 프로그램이 중단되고 작업을 완료할 수 없기 때문에 이는 심각한 문제입니다.

  • 상호 배타적입니다. 조건: 리소스 한 번에 하나의 프로세스에서만 사용할 수 있습니다.
  • 요청 및 보류 조건: 리소스 요청으로 인해 프로세스가 차단되면 획득한 리소스를 유지합니다.
  • 비박탈 조건: 프로세스에서 얻은 자원은 모두 사용되기 전에 강제로 박탈될 수 없습니다.
  • 루프 대기 조건: 여러 프로세스 간에 리소스 관계를 기다리는 일대일 루프가 형성됩니다.

교착 상태를 피하는 가장 간단한 방법은 순환 대기 조건을 방지하고, 플래그를 설정하고 시스템의 모든 리소스를 정렬하며, 모든 프로세스가 특정 순서(오름차순)로 리소스를 신청해야 한다고 규정하는 것입니다. 순서) 또는 내림차순) 교착 상태를 방지합니다.

28) Java에서 라이브락과 교착상태의 차이점은 무엇인가요?

이것은 위 질문의 확장입니다. Livelock은 교착 상태와 유사합니다. 차이점은 Livelock의 스레드 또는 프로세스 상태가 지속적으로 변경되는 것으로 간주할 수 있다는 것입니다. 특별한 종류의 배고픔. 라이브록의 현실적인 예는 좁은 복도에서 두 사람이 만나는 경우인데, 두 사람은 서로 지나갈 수 있도록 서로를 피하려 하지만 회피 방향이 동일하기 때문에 결국 누구도 복도를 통과할 수 없게 된다. 간단히 말해 라이브록과 교착 상태의 주요 차이점은 전자의 경우 프로세스 상태가 변경될 수 있지만 계속 실행할 수는 없다는 것입니다.

29) 스레드가 잠금을 소유하고 있는지 확인하는 방법은 무엇입니까?

전화 인터뷰에 참여하기 전까지는 스레드가 잠금을 소유하고 있는지 실제로 감지할 수 있다는 사실을 전혀 몰랐습니다. java.lang.Thread에는 현재 스레드가 특정 객체에 대한 잠금을 보유하고 있는 경우에만 true를 반환하는holdLock()이라는 메서드가 있습니다.

30) Java에서 스레드 스택을 어떻게 얻나요?

다양한 운영 체제에 대한 Java 프로세스의 스레드 스택을 가져오는 방법에는 여러 가지가 있습니다. 스레드 스택을 얻으면 JVM은 모든 스레드의 상태를 로그 파일에 저장하거나 콘솔에 출력합니다. Windows에서는 Ctrl + Break 키 조합을 사용하여 스레드 스택을 가져올 수 있고 Linux에서는 kill -3 명령을 사용할 수 있습니다. 스레드 ID에서 작동하는 jstack 도구를 사용하여 얻을 수도 있습니다. jps 도구를 사용하여 ID를 찾을 수 있습니다.

31) JVM에서 스레드 스택을 제어하는 ​​데 사용되는 매개변수는 무엇입니까?

이 질문은 매우 간단합니다. -Xss 매개변수가 사용됩니다. 스레드의 스택 크기를 제어합니다.

32) Java에서 동기화와 ReentrantLock의 차이점은 무엇입니까?

Java는 오랫동안 동기화 키워드를 통해서만 상호 배제를 구현할 수 있었는데, 이는 몇 가지 단점이 있습니다. 예를 들어 잠금 외부에서 메서드를 확장하거나 경계를 차단할 수 없으며 잠금을 획득하려고 할 때 중간에 취소할 수 없습니다. Java 5는 이러한 문제를 해결하기 위해 Lock 인터페이스를 통해 보다 복잡한 제어를 제공합니다. ReentrantLock 클래스는 동기화와 동일한 동시성 및 메모리 의미 체계를 가지지만 확장 가능한 Lock을 구현합니다.

33) T1, T2, T3 세 개의 스레드가 순서대로 실행되는지 확인하는 방법은 무엇입니까?

멀티 스레딩에서는 스레드가 특정 순서로 실행되도록 하는 방법이 많이 있습니다. 스레드 클래스의 Join() 메서드를 사용하여 하나의 스레드에서 다른 스레드를 시작할 수 있습니다. 다른 스레드가 완료됩니다. 스레드가 계속 실행됩니다. 세 스레드의 순서를 보장하려면 마지막 스레드를 먼저 시작해야 합니다(T3는 T2 호출, T2는 T1 호출). 그러면 T1이 먼저 완료되고 T3이 마지막으로 완료됩니다.

34) Thread 클래스에서 Yield 메소드의 기능은 무엇인가요?

Yield 메서드는 현재 실행 중인 스레드 개체를 일시 중지하고 동일한 우선 순위를 가진 다른 스레드가 실행되도록 허용할 수 있습니다. 이는 정적 방법이며 현재 스레드가 CPU 점유를 포기한다는 점만 보장하고 다른 스레드가 CPU를 점유할 수 있다는 점은 보장하지 않습니다.

35) Java에서 ConcurrentHashMap의 동시성은 무엇입니까?

ConcurrentHashMap은 확장성과 스레드 안전성을 달성하기 위해 실제 맵을 여러 부분으로 나눕니다. 이 분할은 다중 스레드 상황에서 경합을 피하기 위해 기본값이 16인 ConcurrentHashMap 클래스 생성자의 선택적 매개 변수인 동시성을 사용하여 얻습니다.

36) Java에서 세마포어란 무엇인가요?

Java의 세마포어는 계수 신호인 새로운 동기화 클래스입니다. 개념적으로 세마포어는 허가된 컬렉션을 유지합니다. 필요한 경우 각 acquire()는 권한을 사용할 수 있을 때까지 차단한 다음 권한을 획득합니다. 각 release()는 권한을 추가하여 잠재적으로 차단 획득자를 해제합니다. 그러나 실제 라이센스 객체를 사용하는 대신 Semaphore는 사용 가능한 라이센스 수만 계산하고 적절한 조치를 취합니다. 세마포어는 데이터베이스 연결 풀과 같은 다중 스레드 코드에서 자주 사용됩니다.

37) 작업 제출 시 스레드 풀 대기열이 가득 찬 경우. 회의가 열리면 어떻게 되나요?

이것은 까다로운 질문이며 많은 프로그래머는 스레드 풀 대기열에 공간이 생길 때까지 작업이 차단될 것이라고 생각할 것입니다. 실제로 작업 실행을 예약할 수 없는 경우 ThreadPoolExecutor의 submit() 메서드는 RejectedExecutionException을 발생시킵니다.

38) Java 스레드 풀에서 submit() 메소드와 Execute() 메소드의 차이점은 무엇입니까?

두 메소드 모두 스레드 풀에 작업을 제출할 수 있습니다. Executor 인터페이스에 정의된 실행() 메소드의 반환 유형은 void이고 submit() 메소드는 반환할 수 있습니다. 결과 Future 개체는 Executor 인터페이스를 확장하는 ExecutorService 인터페이스에 정의됩니다. ThreadPoolExecutor 및 ScheduledThreadPoolExecutor와 같은 다른 스레드 풀 클래스에는 이러한 메서드가 있습니다.

39) 차단방법이란 무엇인가요?

차단 방법은 프로그램이 다른 작업을 수행하지 않고 메서드가 완료될 때까지 기다리는 것을 의미합니다. ServerSocket의 accept() 메서드는 클라이언트가 연결될 때까지 기다리는 것입니다. 여기서 차단한다는 것은 호출 결과가 반환되기 전에 현재 스레드가 일시 중단되고 결과를 얻을 때까지 반환되지 않음을 의미합니다. 또한 작업이 완료되기 전에 반환되는 비동기식 및 비차단 메서드가 있습니다.

40) Swing은 스레드로부터 안전합니까? 왜?

Swing이 스레드로부터 안전하지 않다는 것은 확실하게 대답할 수 있지만, 면접관이 이유를 묻지 않더라도 대답한 이유를 설명해야 합니다. Swing이 스레드로부터 안전하지 않다고 말할 때 우리는 종종 해당 구성 요소를 언급합니다. 이러한 구성 요소는 다중 스레드에서 수정할 수 없습니다. GUI 구성 요소에 대한 모든 업데이트는 AWT 스레드에서 완료되어야 하며 Swing은 동기 및 비동기라는 두 가지 콜백 메서드를 제공합니다. . 업데이트합니다.

41) Java에서 InvokeAndWait와 InvokeLater의 차이점은 무엇입니까?

이 두 가지 방법은 이벤트 전달 스레드 대신 현재 스레드에서 GUI 구성 요소를 업데이트하기 위해 Java 개발자에게 Swing API에서 제공됩니다. InvokeAndWait()는 진행률 표시줄과 같은 GUI 구성 요소를 동기적으로 업데이트하고 나면 진행률 표시줄도 이에 따라 변경되어야 합니다. 진행 상황이 여러 스레드에 의해 추적되는 경우에는 InvokeAndWait() 메서드를 호출하여 그에 따라 구성 요소를 업데이트하도록 이벤트 전달 스레드를 요청합니다. InvokeLater() 메서드는 업데이트 구성 요소를 비동기적으로 호출합니다.

42) Swing API의 어떤 메소드가 스레드로부터 안전합니까?

이 질문에서는 스윙 및 스레드 안전성에 대해서도 언급했습니다. 구성 요소가 스레드로부터 안전하지는 않지만 repaint(), 재검증과 같이 여러 스레드에서 안전하게 호출할 수 있는 몇 가지 메서드가 있습니다. (). JTextComponent의 setText() 메소드와 JTextArea의 insert() 및 Append() 메소드도 스레드로부터 안전합니다.

43) Java에서 불변 객체를 만드는 방법은 무엇입니까?

이 문제는 멀티스레딩과 아무 관련이 없는 것처럼 보이지만 불변성은 이미 복잡한 동시 프로그램을 단순화하는 데 도움이 될 수 있습니다. 불변 객체는 동기화 없이 공유될 수 있으므로 객체에 대한 동시 액세스에 대한 동기화 오버헤드가 줄어듭니다. 그러나 Java에는 @Immutable 주석이 없습니다. 불변 클래스를 생성하려면 생성자 메서드를 통해 모든 멤버를 초기화하고, 변수에 대한 setter 메서드를 제공하지 않고, 모든 멤버를 비공개로 선언하여 직접적으로 구현해야 합니다. 이러한 멤버에 액세스할 때는 getter 메서드에서 개체 자체를 직접 반환하지 않고 개체를 복제하고 개체의 복사본을 반환합니다. Java에서 객체를 변경 불가능하게 만드는 방법에 대한 내 기사를 읽고 나면 자신감을 가질 수 있습니다.

44) Java에서 ReadWriteLock이 무엇인가요?

일반적으로 읽기-쓰기 잠금은 동시 프로그램의 성능을 향상시키는 데 사용되는 잠금 분리 기술의 결과입니다. Java의 ReadWriteLock은 Java 5의 새로운 인터페이스입니다. ReadWriteLock은 한 쌍의 관련 잠금을 유지 관리합니다. 하나는 읽기 전용 작업용이고 다른 하나는 쓰기용입니다. 쓰기 스레드가 없으면 여러 읽기 스레드가 동시에 읽기 잠금을 보유할 수 있습니다. 쓰기 잠금은 배타적입니다. JDK에서 ReentrantReadWriteLock을 사용하여 이 규칙을 구현할 수 있습니다. 이는 최대 65535개의 쓰기 잠금과 65535개의 읽기 잠금을 지원합니다.

45) 멀티스레딩에서 비지 루프란 무엇인가요?

비지 루프는 프로그래머가 루프를 사용하여 스레드를 기다리게 만드는 것입니다. , 기존 메소드와 달리 wait(), sleep() 또는 Yield() 메소드는 모두 CPU 제어를 포기하지만 바쁜 루프는 CPU를 포기하지 않고 단지 빈 루프를 실행합니다. 이것의 목적은 CPU 캐시를 보존하는 것입니다. 대기 중인 스레드가 깨어나면 다른 코어에서 실행되어 캐시를 다시 빌드할 수 있습니다. 캐시 재구축을 방지하고 재구축 대기 시간을 줄이기 위해 사용할 수 있습니다.

46) 휘발성 변수와 원자 변수의 차이점은 무엇인가요?

흥미로운 질문이네요. 우선, 휘발성 변수와 원자 변수는 비슷해 보이지만 기능이 다릅니다. 휘발성 변수는 미리보기 관계를 보장할 수 있습니다. 즉, 후속 읽기 작업 전에 쓰기 작업이 발생하지만 원자성을 보장하지는 않습니다. 예를 들어 count 변수가 휘발성으로 수정되면 count++ 작업은 원자적이지 않습니다. AtomicInteger 클래스에서 제공하는 원자적 메서드는 이 작업을 원자적으로 만들 수 있습니다. 예를 들어, getAndIncrement() 메서드는 현재 값에 1을 추가하는 증분 작업을 원자적으로 수행하며 다른 데이터 유형 및 참조 변수에서도 유사한 작업을 수행할 수 있습니다.

47) 동기화된 블록 내부의 스레드에서 예외가 발생하면 어떻게 되나요?

이 질문은 많은 Java 프로그래머를 괴롭혔습니다. 이에 대한 답을 찾기 위해 잠금이 해제되었는지 여부에 대한 단서를 생각해 볼 수 있다면 아마도 올바른 답을 얻을 수 있을 것입니다. 동기화된 블록이 정상적으로 종료되든 비정상적으로 종료되든 내부의 스레드가 잠금을 해제하므로 잠금을 해제하는 데 에너지를 소비하지 않아도 되기 때문에 잠금 인터페이스에 비해 동기화된 블록을 선호합니다. finally 블록에서 잠금을 해제하면 됩니다.

48) 싱글턴 모드의 이중 확인 잠금이 무엇인가요?

자바 면접에서 자주 나오는 질문인데, 면접관들은 이 질문에 대한 답변에 50%만 만족합니다. 절반의 사람들은 이중 확인 잠금을 작성할 수 없으며 절반의 사람들은 숨겨진 위험과 Java 1.5가 이를 수정하는 방법을 설명할 수 없습니다. 실제로는 스레드로부터 안전한 싱글톤을 생성하는 데 사용되는 오래된 방법입니다. 싱글톤 인스턴스를 처음 생성할 때 성능 최적화를 위해 단일 잠금을 사용하려고 시도하지만 JDK1.4에서는 개인적으로 너무 복잡해서 실패합니다. 그것도 마음에 안 들어요. 어쨌든, 마음에 들지 않더라도 자주 묻는 질문이기 때문에 알아 둘 가치가 있습니다.

49) Java에서 스레드로부터 안전한 싱글톤을 만드는 방법은 무엇입니까?

이는 위 질문에 대한 후속 조치입니다. 이중 확인 잠금이 마음에 들지 않고 면접관이 싱글톤 클래스를 생성하는 대체 방법을 묻는 경우 JVM의 클래스 로딩 및 정적 변수 초기화 기능을 사용할 수 있습니다. Singleton 인스턴스를 생성하거나 Enumeration 유형을 사용하여 Singleton을 생성하려면 이 방법을 사용하는 것을 좋아합니다.

50) 따라야 할 멀티스레딩 모범 사례 3가지를 적어 보세요.

이런 종류의 질문은 성능 향상을 위해 동시 코드를 작성할 때도 특정 모범 사례를 따르게 될 것이라고 믿습니다. 다음은 대부분의 Java 프로그래머가 따라야 한다고 생각하는 세 가지 모범 사례입니다.

  • 스레드에 의미 있는 이름을 지정하세요.
    이렇게 하면 버그를 찾거나 추적하는 것이 더 쉬워집니다. OrderProcessor, QuoteProcessor 또는 TradeProcessor는 Thread-1, Thread-2 및 Thread-3보다 훨씬 더 나은 이름입니다. 모든 주요 프레임워크와 JDK도 이 모범 사례를 따릅니다.
  • 잠금을 피하고 동기화 범위를 줄이세요.
    잠금은 비용이 많이 들고 컨텍스트 전환에는 더 많은 시간과 공간이 필요합니다. 중요한 섹션을 줄이려면 동기화와 잠금을 최소한으로 사용하세요. 그러므로 나는 동기화된 방법보다 동기화된 블록을 선호하며, 이는 나에게 잠금에 대한 절대적인 제어를 제공합니다.
  • 동기화 클래스를 더 많이 사용하고 대기 및 알림을 덜 사용하세요.
    우선 CountDownLatch, Semaphore, CyclicBarrier 및 Exchanger와 같은 동기화 클래스는 코딩 작업을 단순화하는 반면 대기 및 알림을 사용하여 복잡한 제어 흐름을 제어하기는 어렵습니다. 둘째, 이러한 클래스는 최고의 회사에서 작성하고 유지 관리하며, 이러한 상위 수준 동기화 도구를 사용하면 후속 JDK에서 지속적으로 최적화되고 개선됩니다.
  • 더 많은 동시 컬렉션과 덜 동기화된 컬렉션 사용
    이것은 따르기 쉽고 큰 이점이 있는 또 다른 모범 사례입니다. 동시 컬렉션은 동기화 컬렉션보다 확장성이 뛰어나므로 동시에 프로그래밍할 때 동시 컬렉션을 사용하는 것이 더 좋습니다. 다음에 map을 사용해야 한다면 먼저 ConcurrentHashMap을 사용하는 것을 생각해야 합니다.

51) 스레드를 강제로 시작하는 방법은 무엇입니까?

이 질문은 Java 가비지 수집을 강제하는 방법과 같습니다. 현재 System.gc()를 사용하여 가비지 수집을 수행할 수는 있지만 성공할 것이라는 보장은 없습니다. Java에서는 스레드를 강제로 시작할 수 있는 방법이 없으며 스레드 스케줄러에 의해 제어되며 Java는 관련 API를 게시하지 않습니다.

52) Java의 포크 조인 프레임워크란 무엇입니까?

포크 조인 프레임워크는 JDK7에 등장한 효율적인 도구로, 이를 통해 Java 개발자는 최신 서버의 다중 프로세서를 최대한 활용할 수 있습니다. 이는 프로그램 성능을 향상시키기 위해 사용 가능한 모든 처리 능력을 사용하기 위해 여러 하위 모듈로 반복적으로 나눌 수 있는 응용 프로그램을 위해 특별히 설계되었습니다. 포크 조인 프레임워크의 가장 큰 장점은 작업 도용 알고리즘을 사용한다는 것입니다. 더 많은 작업을 완료할 수 있는 작업자 스레드는 실행을 위해 다른 스레드에서 작업을 훔칠 수 있습니다.

53) Java 멀티스레딩에서 wait() 메소드와 sleep() 메소드 호출의 차이점은 무엇입니까?

Java 프로그램의 대기 및 절전 모드는 모두 일종의 일시 중지를 유발하며 서로 다른 요구 사항을 충족할 수 있습니다. wait() 메서드는 스레드 간 통신에 사용되며 대기 조건이 true이고 다른 스레드가 활성화되면 잠금을 해제하는 반면 sleep() 메서드는 CPU 리소스만 해제하거나 현재 스레드의 실행을 중지합니다. 하지만 잠금을 해제하지는 않습니다.

자바 관련 면접 지식이 더 궁금하시다면 자바 면접 질문 칼럼을 참고해주세요!

위 내용은 수집할 가치가 있는 Java 멀티스레딩 인터뷰 질문(답변 포함)의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!

성명:
이 기사는 segmentfault.com에서 복제됩니다. 침해가 있는 경우 admin@php.cn으로 문의하시기 바랍니다. 삭제