スレッド割り込みメカニズムは、ターゲットスレッドの既存の処理フローを中断し、新しいコマンドに応答しようとするブロッキング待機からスレッドを目覚めさせる方法を提供します。 Javaはこの自由を開発者に残し、それをうまく利用する必要があります。
今日は、Javaスレッドの割り込みメカニズムについて説明します。
スレッド割り込みメカニズムは、2つの一般的な用途を持つメソッドを提供します。
ブロッキング待機からスレッドを目覚めさせ、対応する「制御された割り込み」処理を行います。
ターゲットスレッドに通知してみてください。既存の処理フローを中断し、新しいコマンドに応答してください。
最初の目的を例にとって、次のコードを参照してください。
同期(lock){try {while(!check()){lock.wait(1000); }} catch(arturnedexception e){e.printstacktrace(); }}このコードは、Javaが提供する待機/通知メカニズムを使用します。 lock.wait()のスレッド実行がブロックされます。実行するスレッドを復元する3つの状況があります。
1.タイムアウト1000msは終了し、次のコードは正常に実行されます。
2。別のスレッドが次のコードを実行して積極的に目を覚ます
同期(lock){lock.notifyall(); //またはlock.notify();}これにより、次のコードも正常に実行されます。
3。待機する必要がある別のスレッドは「割り込み」です
//待機中のスレッドa; a.interrupt()への参照を取得します。
「中断された」スレッドAは、lock.wait()で中断されたexception例外をスローします。
要約すると、object.wait()がこれらのことを内部的に行っていると考えることができます。
boolean checktimeout = timeout> 0; thread current = thread.currentthread(); lock.addwaiter(current); while(!current.isnotified()){if(current.isinterpurded()){current.ClearInterrupted(); new interruptedexception(); } if(checktimeout){if(timeout == 0)break;タイムアウト - ; }}これは完全に正確ではありません。なぜなら、待機はこの「忙しいポーリング」方法を使用して確認するためではないが、フラグビットを判断するロジックは正しいからです。
上記の「手動での割り込み」操作から始めましょう
// sun.nio.ch.interruptiblepublic interface割り込み可能{void interrument(thread var1);} // java.lang.threadprivate揮発性中断ブロッカー;プライベート最終オブジェクトblockerlock = new object(); public void interration(){if(this!= thread.currentthth);同期(blockerlock){割り込み可能なb = blocker; if(b!= null){instruct0(); b.Interrupt(this);戻る; }} intertrid0();} // indurtion flagprivateネイティブvoid interrupt0()を設定するためだけに;thread.interrupt()First Judges Permissionsが許可され、実際にincration0()を呼び出してスレッドの割り込みフラグを設定することがわかります。現在のスレッドにNIOの割り込み可能な場合は、コールバックされます。
naturt0()は、スレッドの割り込みフラグを設定するだけであることに注意してください。
スレッドがブロックされておらず、object.wait()、thread.join()、thread.sleep()などのJavaプログラムロジックによって制御されていない領域にない場合はどうなりますか?答えは、何も起こらないということです。また、スレッドが中断されているかどうかは、割り込みフラグを積極的にチェックすることによってのみ知られることです。
チェックする方法は? Threadは、2つのインターフェイスを公開します。Thread.Interrupded()とthread.isIstrupted()。
// java.lang.threadpublic static boolean挿入(){return currentthread()。is utterrupted(true);} public boolean is unterrupted(){return interdurded(false);}プライベートネイティブブーリアンis途中で(boolean clearinderrupted);どちらも内部に依存していることがわかります。
関数呼び出しがブロックすると、Javaライブラリ関数マークは、ブロッキングソースの署名で中断されたエクセプトをマークし、割り込みを処理するために書き込みトライキャッチを必要とします。
上記のように、スレッドがブロックされると、Javaは割り込みフラグをチェックし、最初にクリアし、その後中断拡張エクセプトをスローします。
// java.lang.objectpublic final void wait()throws arturtedexception {wait(0);} public final native void wait(long timeout)throws interrutedexception;スレッドが中断されたExceptionを受信してから、ブロッキングをスローするコードを実行すると、「関係なく」のようにブロックされ続けます。 Javaは内部的に割り込みフラグをクリアするからです!
私たちはしばしば、中断されたエクセプトを処理する次の3種類のコードを書きます。
処理のために中断のエクセプトを上層層に処理します。
public void foo()throws arturnedexception {synchronized(lock){lock.wait(); }}割り込みExceptionは、割り込みフラグビットをリセットします。
try {synchronized(lock){lock.wait(); }} catch(arturnedexception e){thread.currentthread()。arturn(); //壊す; }最初に作業を終えてから、もう一度中断したExceptionを投げます。
public void bar()throws arturnedexception {arturtedexception ie = null; boolean done = false; while(!done){synchronized(lock){try {lock.wait(); } catch(arternedexception e){ie = e;続く; }} done = true; } if(ie!= null){throw ie; }}スレッドが割り込みフラグを無視し、断続的なエクセプトを中断した場合、それでもうまく実行されます。しかし、これはマルチスレッドを設計するという当初の意図に反しています。特定の機能を達成するために、調和して整然と整理するようにスレッドが協力することを望んでいるので、制御されたスレッドは割り込みに応答するはずです。そして、私たちはJavaによって開発者に残されたこの自由をうまく利用すべきです。
上記は、今回紹介されたJavaスレッド割り込みメカニズムに関するすべての関連知識です。何も理解していない場合は、以下のメッセージ領域で説明できます。 wulin.comへのご支援ありがとうございます。