>  기사  >  Java  >  Java에서 높은 동시성 InterruptedException 문제를 해결하는 방법

Java에서 높은 동시성 InterruptedException 문제를 해결하는 방법

WBOY
WBOY앞으로
2023-04-30 08:46:061601검색

머리말

InterruptedException은 생각만큼 간단하지 않을 수 있습니다!

Java 객체의 wait() 메서드나 스레드의 sleep() 메서드를 호출할 때 InterruptedException 예외를 포착하고 처리해야 합니다. InterruptedException을 부적절하게 처리하면 예상치 못한 결과가 발생합니다!

Program Case

예를 들어 다음 프로그램 코드에서 InterruptedTask 클래스는 Runnable 인터페이스를 구현합니다. run() 메서드에서는 현재 스레드의 핸들을 가져오고 while(true) 루프에서는 현재 스레드를 가져옵니다. 스레드가 중단되었는지 여부는 현재 스레드가 중단된 경우 while(true) 루프를 종료하는 동시에 다음 줄도 있습니다. Thread.sleep(100) 코드 및 InterruptedException 예외가 캡처됩니다.

전체 코드는 아래와 같습니다.

package io.binghe.concurrent.lab08;
/**
 * @author binghe
 * @version 1.0.0
 * @description 线程测试中断
 */
public class InterruptedTask implements Runnable{
    @Override
    public void run() {
        Thread currentThread = Thread.currentThread();
        while (true){
            if(currentThread.isInterrupted()){
                break;
            }
            try {
                Thread.sleep(100);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
}

위 코드의 원래 의도는 isInterrupted() 메서드를 통해 스레드가 중단되었는지 여부를 확인하고, 중단되면 while 루프를 종료하는 것입니다. 이때 다른 스레드는 실행 스레드의 Interrupt() 메서드를 호출하여 실행 스레드를 중단시킵니다. 이때 실행 스레드의 인터럽트 플래그 비트가 설정되므로 currentThread.isInterrupted()가 true를 반환하므로 while 루프를 실행할 수 있습니다. 나갔다.

이건 문제 없을 것 같습니다! 근데 정말 그럴까요? 테스트를 위해 InterruptedTest 클래스를 생성합니다. 코드는 다음과 같습니다.

package io.binghe.concurrent.lab08;
/**
 * @author binghe
 * @version 1.0.0
 * @description 测试线程中断
 */
public class InterruptedTest {
    public static void main(String[] args){
        InterruptedTask interruptedTask = new InterruptedTask();
        Thread interruptedThread = new Thread(interruptedTask);
        interruptedThread.start();
        try {
            Thread.sleep(1000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        interruptedThread.interrupt();
    }
}

아래 그림과 같이 main 메소드를 실행합니다.

Java에서 높은 동시성 InterruptedException 문제를 해결하는 방법

문제 분석

위 코드는 스레드를 중단하기 위해 스레드의 Interrupt() 메서드를 명확하게 호출하지만 아무런 효과가 없습니다. 그 이유는 스레드의 run() 메서드가 실행될 때 대부분의 경우 sleep(100)에서 차단되기 때문입니다. 다른 스레드가 실행 스레드의 Interrupt() 메서드를 호출하여 실행 스레드를 중단하면 InterruptedException이 발생합니다. 높은 확률 예외, InterruptedException 예외가 발생하면 JVM은 동시에 스레드의 인터럽트 플래그 비트를 삭제하므로 이때 run() 메서드에서 판단된 currentThread.isInterrupted()는 false를 반환합니다. 현재 while 루프는 종료되지 않습니다.

문제 분석이 완료되었으니 스레드를 중단하고 프로그램을 종료하는 방법은 무엇인가요?

문제 해결

이를 처리하는 올바른 방법은 InterruptedTask 클래스의 run() 메소드에 있는 while(true) 루프에서 예외를 포착한 다음 인터럽트 플래그 비트를 재설정하는 것입니다. InterruptedTask 클래스의 올바른 코드는 다음과 같습니다.

package io.binghe.concurrent.lab08;
/**
 * @author binghe
 * @version 1.0.0
 * @description 中断线程测试
 */
public class InterruptedTask implements Runnable{
    @Override
    public void run() {
        Thread currentThread = Thread.currentThread();
        while (true){
            if(currentThread.isInterrupted()){
                break;
            }
            try {
                Thread.sleep(100);
            } catch (InterruptedException e) {
                e.printStackTrace();
                currentThread.interrupt();
            }
        }
    }
}

보시다시피 InterruptedException 예외를 캡처하는 catch 코드 블록에 새로운 코드 줄을 추가했습니다.

currentThread.interrupt();

이를 통해 InterruptedException 예외를 포착한 후 스레드의 인터럽트 플래그 비트를 재설정하여 현재 실행 중인 스레드를 중단할 수 있습니다.

InterruptedTest 클래스의 메인 메소드를 아래와 같이 다시 실행합니다.

Java에서 높은 동시성 InterruptedException 문제를 해결하는 방법

요약

InterruptedException을 처리할 때 주의하세요. 실행 스레드를 중단하기 위해 실행 스레드의 Interrupt() 메서드를 호출할 때 InterruptedException이 발생하면 InterruptedException 예외가 트리거될 때 JVM이 동시에 중단합니다. 이때, 실행 스레드의 isInterrupted() 메서드가 호출되면 false가 반환됩니다.

이때, 올바른 처리 방법은 실행 스레드의 run() 메서드에서 InterruptedException 예외를 catch하고 인터럽트 플래그 비트를 재설정하는 것입니다(즉, InterruptedException 예외를 catch하는 catch 코드 블록에서 다시 -현재 스레드의 인터럽트() 메서드를 호출합니다.

위 내용은 Java에서 높은 동시성 InterruptedException 문제를 해결하는 방법의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!

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