English | 简体中文 | 繁體中文 | Русский язык | Français | Español | Português | Deutsch | 日本語 | 한국어 | Italiano | بالعربية
스레드 중지 메커니즘은 스레드를 블록된 대기 상태에서 깨우고, 목표 스레드의 현재 처리 프로세스를 중지하고 새 명령에 응답하려는 방법을 제공합니다. Java는 개발자에게 이 자유를 주었으므로 적절히 사용해야 합니다.
오늘은 Java 스레드의 중지 메커니즘에 대해 이야기해 보겠습니다.
스레드 중지 메커니즘은 두 가지 일반적인 용도를 제공합니다:
스레드를 블록된 대기 상태에서 깨우고 적절한 "제어된 중지" 처리를 수행합니다.
목표 스레드에 알림을 전달하려고 시도합니다: 현재 처리 프로세스를 중지하고 새 명령에 응답하십시오.
첫 번째 용도로 예를 들어, 다음 코드를 보세요:
synchronized (lock) { try { while (!check()) { lock.wait(1000); } } e.printStackTrace(); } }
이 코드는 Java가 제공하는 wait를 사용합니다/notify 메커니즘, 스레드가 lock.wait()을 수행할 때는 블록됩니다. 스레드가 다시 실행되는 세 가지 상황이 있습니다.
1시간 초과 1000ms 완료, 정상적으로 다음 코드를 실행합니다.
2또 다른 스레드가 다음 코드를 실행하여 적극적으로 깨우기
synchronized (lock) { lock.notifyAll(); // 또는 lock.notify(); }
이는 정상적으로 다음 코드를 실행합니다.
3또 다른 스레드가 대기 중인 스레드를 "중지"하려고 요청합니다
// 대기 중인 스레드의 참조를 얻습니다 Thread a; a.interrupt();
락.wait()에서 InterruptedException 예외가 발생하는 "중지"된 스레드 a가 있습니다.
따라서 object.wait() 내부에서 이러한 작업을 수행한다고 생각할 수 있습니다:
boolean checkTimeout = timeout > 0; Thread current = Thread.currentThread(); lock.addWaiter(current); while (!current.isNotified()) { if (current.isInterrupted()) { current.clearInterrupted(); throw new InterruptedException(); } if (checkTimeout) { if (timeout == 0) break; timeout--; } }
이는 완전히 정확하지 않습니다. 왜냐하면 wait는 이러한 '버스터 루프' 방식을 사용하지 않기 때문입니다. 그러나 플래그의 판단 로직은 올바르습니다.
위에서 설명한 '수동으로 중단 발생' 이야기부터 탐구해 보겠습니다.
// sun.nio.ch.Interruptible public interface Interruptible { void interrupt(Thread var1); } // java.lang.Thread private volatile Interruptible blocker; private final Object blockerLock = new Object(); public void interrupt() { if (this != Thread.currentThread()) checkAccess(); synchronized (blockerLock) { Interruptible b = blocker; if (b != null) { interrupt0(); b.interrupt(this); return; } } interrupt0(); } // 중단 플래그만 설정하기 위해 private native void interrupt0();
thread.interrupt()는 권한을 먼저 확인한 후 interrupt0()를 호출하여 스레드의 중단 플래그를 설정합니다. 현재 스레드가 nio의 Interruptible을 가지고 있다면 그것을 콜백할 수도 있습니다.
주의하십시오. interrupt0()는 단지 스레드의 중단 플래그를 설정합니다.
当一个线程并不阻塞,没有在 object.wait(), thread.join(), Thread.sleep() 등不受 Java 프로그램 로직控制的区域时,那么会发生什么事情?答案是不会有任何事情发生,线程是否被打断只能通过主动地检查中断标志得知。
怎么检查?Thread는 두 개의 인터페이스를 노출합니다, Thread.interrupted()와 thread.isInterrupted()。
// java.lang.Thread public static boolean interrupted() { return currentThread().isInterrupted(true); } public boolean isInterrupted() { return isInterrupted(false); } private native boolean isInterrupted(boolean clearInterrupted);
能够看出,两者都是依靠内部的 isInterrupted(boolean),而它会返回线程是否被打断,并根据需要清空中断标志。
当一个函数调用会发生阻塞时,Java 라이브러리 함수는 블로킹 원천에서 throws InterruptedException를 표시하고, 중지를 처리하기 위해 try catch를 작성하도록 요구합니다.
当线程发生了阻塞,就像上文所述,Java는 중지 기호를 검사하고, 먼저 지우고, InterruptedException를 throw합니다.
// java.lang.Object public final void wait() throws InterruptedException { wait(0); } public final native void wait(long timeout) throws InterruptedException;
如果一个线程收到 InterruptedException 후에도 블로킹 코드를 계속 실행하면, 그것은 '사람이 없는 것처럼' 계속 블로킹됩니다. 왜냐하면 Java는 내부에서 중지 기호를 지우기 때문입니다!
我们常见地编写以下三类处理 InterruptedException의 코드를 작성합니다:
InterruptedException를 상위 레이어에 처리하도록 합니다。
public void foo() throws InterruptedException { synchronized (lock) { lock.wait(); } }
InterruptedException을 만나면 중지 시그널 비트를 다시 설정합니다.
try { synchronized (lock) { lock.wait(); } } Thread.currentThread().interrupt(); //break; }
먼저 일을 마침, 그런 다음 InterruptedException을 다시 던져 주세요.
public void bar() throws InterruptedException { InterruptedException ie = null; boolean done = false; while (!done) { synchronized (lock) { try { lock.wait(); } ie = e; continue; } } done = true; } if (ie != null) { throw ie; } }
스레드가 중지 시그널과 InterruptedException를 무시하면 여전히 잘 실행될 수 있습니다. 하지만 이는 우리가 다중 스레드를 설계한 원래 목적과는 다릅니다. 우리는 특정 기능을 수행하기 위해 스레드 간의 조화로운 유序 협력을 원합니다. 따라서 제어된 스레드는 중지에 대한 응답을 해야 합니다. Java는 개발자에게 이 자유를 주었으니, 우리는 이를 잘 활용해야 합니다.
이번에 제공한 Java 스레드의 중지 메커니즘에 대한 모든 내용을 다루었습니다. 이해가 잘 안 되는 부분이 있으시면 아래의 댓글 영역에서 논의해 주세요.呐喊 강의에 대한 지지에 감사합니다.
고지: 이 문서의 내용은 인터넷에서 가져왔으며, 저작권은 원작자에게 있으며, 인터넷 사용자가 자발적으로 기여하고 자체로 업로드한 내용입니다. 이 사이트는 소유권을 가지지 않으며, 인공적으로 편집한 것도 아니며, 관련 법적 책임도 부담하지 않습니다. 저작권 침해가 의심되는 내용이 있으시면 notice#w로 이메일을 보내 주시기 바랍니다.3codebox.com(보내는 이메일에서 #을 @으로 변경하시오)를 통해 신고하시고 관련 증거를 제공하시면, 실제로 확인되면 이 사이트는 즉시 저작권 침해 내용을 삭제할 것입니다。