先週の金曜日と週末、忙しい仕事を休んで、Java cocurrent を見ながら Java 5 以降の Thread.interrupt と LockSupport の実装をレビューしました。
紹介する前に、いくつか質問させてください。
Thread.interrupt() メソッドと InterruptedException の関係は何ですか? InterruptedException 例外は割り込みによってトリガーされますか?
Thread.interrupt() はどのような状態でスレッドの作業を中断しますか?実行中ですか、それともブロック中ですか?
一般的なスレッドプログラミングでは割り込みに注意を払う必要がありますか?一般的にはどのように対処すればよいのでしょうか?何に使えますか?
LockSupport.park()とunpark()、object.wait()とnotify()の違いは何ですか?
LockSupport.park(Object blocker) によって渡されるブロッカー オブジェクトは何に使用されますか?
LockSupport は Thread.interrupt() イベントに応答できますか? InterruptedException がスローされるでしょうか?
Thread.interrupt() 処理に対応するコールバック関数はありますか?フックコールみたいなものでしょうか?
すべてに明確に答えることができた場合は、Thread.interrupt をすでに完全に理解していることを意味するため、これ以上読む必要はありません。
それでもわからない場合は、これらの質問と合わせて整理してみましょう。
スレッドの割り込みを処理するためのいくつかの方法:
public void中断(): スレッド割り込みイベントを実行します。
public boolean isInterrupted() : 現在のスレッドが中断されているかどうかを確認します
public static boolean Interrupted(): 現在のスレッドが割り込まれているかどうかを確認し、割り込み情報をリセットします。リセットアンドゲット()に似ている
理解する:
1. 各スレッドには、現在のスレッドが割り込み状態にあるかどうかを示す割り込みステータス フラグがあります。
2. 一般に、object.wait()、object.sleep()、object.join() など、優先度の低いブロック状態に遭遇したときに Thread.interrupt() を呼び出すときの処理方法は 2 つあります。すぐにブロック解除をトリガーしてブロックを解除し、InterruptedException をスローします。
それ以外の場合、Thread.interrupt() はステータス フラグのみを更新します。その後、ワーカー スレッドは Thread.isInterrrupted() を介してチェックし、InterruptedException のスローやステータスのクリア、タスクのキャンセルなどの対応する処理を実行できます。
割り込みJavadocで説明されています:
ベストプラクティス
IBM に関する非常に優れた記事があります。 Java の理論と実践: InterruptedException の処理。割り込み処理のいくつかのベスト プラクティスについて説明します。
割り込みを飲み込まないでください (割り込みを飲み込まないでください。通常、処理には 2 つのタイプがあります。1 つは InterruptedException をスローし続けることです。もう 1 つは、Thread.interupt() 例外フラグを設定し続けることで、上位レベルがそれに応じて処理できるようにします。
次のようにコードをコピーします。
public class TaskRunner は Runnable {を実装します。
プライベート BlockingQueue<Task> キュー;
public TaskRunner(BlockingQueue<タスク> キュー) {
this.queue = キュー;
}
public void run() {
試す {
while (true) {
タスク task = queue.take(10, TimeUnit.SECONDS);
task.execute();
}
}
catch (InterruptedException e) {
// 中断された状態を復元します
Thread.currentThread().interrupt();
}
}
}
次のようにコードをコピーします。
public class TaskRunner は Runnable {を実装します
プライベート BlockingQueue<Task> キュー;
public TaskRunner(BlockingQueue<タスク> キュー) {
this.queue = キュー;
}
public void run() {
試す {
while (true) {
タスク task = queue.take(10, TimeUnit.SECONDS);
task.execute();
}
}
catch (InterruptedException e) {
// 中断された状態を復元します
Thread.currentThread().interrupt();
}
}
}
割り込みを使用したキャンセル可能なタスクの実装 (キャンセル可能なタスクの設計とサポートには Thread.interrupt() を使用します)
次のようにコードをコピーします。
public class PrimeProducer extends Thread {
プライベート最終 BlockingQueue<BigInteger> キュー;
PrimeProducer(BlockingQueue<BigInteger> キュー) {
this.queue = キュー;
}
public void run() {
試す {
BigInteger p = BigInteger.ONE;
while (!Thread.currentThread().isInterrupted())
queue.put(p = p.nextProbablePrime());
} catch (InterruptedException が消費されました) {
/* スレッドの終了を許可します */
}
}
public void cancel() {interrupt() } // 割り込みを開始します。
}<SPAN style="WHITE-SPACE:normal"> </SPAN>
次のようにコードをコピーします。
public class PrimeProducer extends Thread {
プライベート最終 BlockingQueue<BigInteger> キュー;
PrimeProducer(BlockingQueue<BigInteger> キュー) {
this.queue = キュー;
}
public void run() {
試す {
BigInteger p = BigInteger.ONE;
while (!Thread.currentThread().isInterrupted())
queue.put(p = p.nextProbablePrime());
} catch (InterruptedException が消費されました) {
/* スレッドの終了を許可します */
}
}
public void cancel() {interrupt() } // 割り込みを開始します。
}<SPAN style="WHITE-SPACE:normal"> </SPAN>
割り込み処理イベントの登録(異常使用)
一般に、通常のタスクはキャンセルを処理するように設計されており、すべてアクティブ ポーリングを使用して Thread.isInterrupt() をチェックします。これはビジネス自体にある程度組み込まれており、次のタスクまで待機する必要があります。チェックポイント (次のチェックポイントがいつになるかは誰にもわかりません。特に、socket.read を実行するときに、HttpClient のタイムアウトの問題が発生しました)。
InterruptedException を積極的にスローする実装は、非常に賢い InterruptibleChannel の設計に基づいています。
次のようにコードをコピーします。
Interface InterruptAble { // 割り込み可能なインターフェイスを定義する
public voidinterrupt() は InterruptedException をスローします。
}
抽象クラス InterruptSupport は InterruptAble {を実装します。
プライベート揮発性ブール値の中断 = false;
private 割り込み可能なインタラプタ = new Interruptible() {
パブリック void 割り込み() {
中断 = true;
InterruptSupport.this.interrupt(); // 位置 3
}
};
public Final booleanexecute() は InterruptedException をスローします {
試す {
BlockedOn(interruptor); // 位置 1
if (Thread.currentThread().isInterrupted()) { // すぐに中断される
インタラプタ.インタラプト();
}
//ビジネスコードを実行する
ビジネス();
} ついに {
blockOn(null); // 位置 2
}
リターンが中断されました。
}
パブリック抽象 void business() ;
パブリック抽象無効割り込み();
// -- sun.misc.SharedSecrets --
static void blockOn(Interruptible intr) { // package-private
sun.misc.SharedSecrets.getJavaLangAccess().blockedOn(Thread.currentThread(), intr);
}
}
次のようにコードをコピーします。
Interface InterruptAble { // 割り込み可能なインターフェイスを定義する
public voidinterrupt() は InterruptedException をスローします。
}
抽象クラス InterruptSupport は InterruptAble {を実装します。
プライベート揮発性ブール値の中断 = false;
private 割り込み可能なインタラプタ = new Interruptible() {
パブリック void 割り込み() {
中断 = true;
InterruptSupport.this.interrupt(); // 位置 3
}
};
public Final booleanexecute() は InterruptedException をスローします {
試す {
BlockedOn(interruptor); // 位置 1
if (Thread.currentThread().isInterrupted()) { // すぐに中断される
インタラプタ.インタラプト();
}
//ビジネスコードを実行する
ビジネス();
} ついに {
blockOn(null); // 位置 2
}
リターンが中断されました。
}
パブリック抽象 void business() ;
パブリック抽象無効割り込み();
// -- sun.misc.SharedSecrets --
static void blockOn(Interruptible intr) { // package-private
sun.misc.SharedSecrets.getJavaLangAccess().blockedOn(Thread.currentThread(), intr);
}
}
コードの説明といくつかのトリック:
位置 1: sun が提供する BlockedOn メソッドを使用して、対応する割り込みイベント処理フックを指定されたスレッドにバインドします。
位置 2: コードの実行後、フックをクリアします。接続プールを使用する場合は、次のスレッド処理イベントへの影響を回避します。
位置 3: 割り込みイベント フックの処理メソッドを定義し、InterruptSupport.this.interrupt() メソッドをコールバックします。サブクラスは、ソック ストリームのクローズなど、独自のビジネス ロジックを統合して実装できます。
使用:
次のようにコードをコピーします。
class InterruptRead extends InterruptSupport {
プライベート FileInputStream で;
@オーバーライド
public void business() {
File file = new File("/dev/urandom"); // Linux ブラックホールを読み続けます。読み終わることはありません。
試す {
in = 新しい FileInputStream(ファイル);
byte[] バイト = 新しいバイト [1024];
while (in.read(bytes, 0, 1024) > 0) {
// Thread.sleep(100);
// if (Thread.interrupted()) {// 前の割り込みチェックメソッド
// new InterruptedException("") をスローします。
// }
}
} catch (例外 e) {
新しい RuntimeException(e) をスローします。
}
}
public FileInputStream getIn() {
戻ってください。
}
@オーバーライド
パブリック void 割り込み() {
試す {
in.getChannel().close();
} キャッチ (IOException e) {
e.printStackTrace();
}
}
}
public static void main(String args[]) throws Exception {
最終的な InterruptRead テスト = new InterruptRead();
スレッド t = 新しいスレッド() {
@オーバーライド
public void run() {
ロングスタート = System.currentTimeMillis();
試す {
System.out.println("InterruptRead start!");
test.execute();
} catch (InterruptedException e) {
System.out.println("InterruptRead 終了! コスト時間 : " + (System.currentTimeMillis() - start));
e.printStackTrace();
}
}
};
t.start();
// 最初に Read を 3 秒間実行します
Thread.sleep(3000);
//割り込みを発行する
t.interrupt();
}
次のようにコードをコピーします。
class InterruptRead extends InterruptSupport {
プライベート FileInputStream で;
@オーバーライド
public void business() {
File file = new File("/dev/urandom"); // Linux ブラックホールを読み続けます。読み終わることはありません。
試す {
in = 新しい FileInputStream(ファイル);
byte[] バイト = 新しいバイト [1024];
while (in.read(bytes, 0, 1024) > 0) {
// Thread.sleep(100);
// if (Thread.interrupted()) {// 前の割り込みチェックメソッド
// new InterruptedException("") をスローします。
// }
}
} catch (例外 e) {
新しい RuntimeException(e) をスローします。
}
}
public FileInputStream getIn() {
戻ってください。
}
@オーバーライド
パブリック void 割り込み() {
試す {
in.getChannel().close();
} キャッチ (IOException e) {
e.printStackTrace();
}
}
}
public static void main(String args[]) throws Exception {
最終的な InterruptRead テスト = new InterruptRead();
スレッド t = 新しいスレッド() {
@オーバーライド
public void run() {
ロングスタート = System.currentTimeMillis();
試す {
System.out.println("InterruptRead start!");
test.execute();
} catch (InterruptedException e) {
System.out.println("InterruptRead 終了! コスト時間 : " + (System.currentTimeMillis() - start));
e.printStackTrace();
}
}
};
t.start();
// 最初に Read を 3 秒間実行します
Thread.sleep(3000);
//割り込みを発行する
t.interrupt();
}
JDK ソースコードの紹介:
1. sun が提供するフックは、システムの関連コード、行: 1125 を表示できます。
次のようにコードをコピーします。
sun.misc.SharedSecrets.setJavaLangAccess(new sun.misc.JavaLangAccess(){
public sun.reflect.ConstantPool getConstantPool(Class klass) {
戻り klass.getConstantPool();
}
public void setAnnotationType(クラス klass, AnnotationType タイプ) {
klass.setAnnotationType(タイプ);
}
public AnnotationType getAnnotationType(Class klass) {
戻り klass.getAnnotationType();
}
public <E extends Enum<E>>
E[] getEnumConstantsShared(Class<E> klass) {
klass.getEnumConstantsShared() を返します。
}
public void blockOn(スレッド t, 割り込み可能 b) {
t.blockedOn(b);
}
});
次のようにコードをコピーします。
sun.misc.SharedSecrets.setJavaLangAccess(new sun.misc.JavaLangAccess(){
public sun.reflect.ConstantPool getConstantPool(Class klass) {
戻り klass.getConstantPool();
}
public void setAnnotationType(クラス klass, AnnotationType タイプ) {
klass.setAnnotationType(タイプ);
}
public AnnotationType getAnnotationType(Class klass) {
戻り klass.getAnnotationType();
}
public <E extends Enum<E>>
E[] getEnumConstantsShared(Class<E> klass) {
klass.getEnumConstantsShared() を返します。
}
public void blockOn(スレッド t, 割り込み可能 b) {
t.blockedOn(b);
}
});
2. Thread.interrupt()
次のようにコードをコピーします。
パブリック void 割り込み() {
if (this != Thread.currentThread())
checkAccess();
同期化 (ブロッカーロック) {
中断可能な b = ブロッカー。
if (b != null) {
interrupt0(); // 割り込みフラグを設定するだけです
b.interrupt(); //コールバックフック
戻る;
}
}
割り込み0();
}
次のようにコードをコピーします。
パブリック void 割り込み() {
if (this != Thread.currentThread())
checkAccess();
同期化 (ブロッカーロック) {
中断可能な b = ブロッカー。
if (b != null) {
interrupt0(); // 割り込みフラグを設定するだけです
b.interrupt(); //コールバックフック
戻る;
}
}
割り込み0();
}
Thread.stop、suspend、resume、interrupt の使用方法の詳細については、http://download.oracle.com/javase/6/docs/technotes/guides/concurrency などの Sun のドキュメントを参照してください。 /threadPrimitiveDeprecation .html
最後に、これまでの質問のいくつかに答えてみましょう。
質問 1: Thread.interrupt() メソッドと InterruptedException の関係は何ですか? InterruptedException 例外は割り込みによってトリガーされますか?
回答: Thread.interrupt() は、Object.wait()、.Object.join()、および Object.sleep() でのみ InterruptedException を積極的にスローします。 Threadのフラグ情報を設定するだけで他のブロックでも共通であり、プログラム自身が処理する必要があります。
次のようにコードをコピーします。
if (Thread.interrupted()) // 中断ステータスをクリアします!
新しい InterruptedException() をスローします。
次のようにコードをコピーします。
if (Thread.interrupted()) // 中断ステータスをクリアします!
新しい InterruptedException() をスローします。
質問 2: Thread.interrupt() はどのような状態でスレッドの作業を中断しますか?実行中ですか、それともブロック中ですか?
回答: Thread.interrupt 設計の目的は主に、wait() 状態や sleep() 状態などのブロック状態のスレッドを処理することです。ただし、タスクのキャンセルはプログラム設計時にサポートでき、RUNNING 状態もサポートできます。たとえば、Object.join() や割り込みをサポートする一部の nio チャネル設計などです。
質問 3: 一般的なスレッド プログラミングでは割り込みに注意を払う必要がありますか?一般的にはどのように対処すればよいのでしょうか?何に使えますか?
回答: 割り込みの使用法: ブロック解除操作、タスクのキャンセル、データ クリーニングなどをサポートします。
質問4: LockSupport.park()とunpark()、object.wait()とnotify()の違いは何ですか?
答え:
1. 主題が異なります。 LockSuport は主に Thread のブロッキング処理を実行します。ブロッキング キューの対象オブジェクトを指定し、毎回起動する特定のスレッドを指定できます。 Object.wait() はオブジェクトをディメンションとして受け取り、現在のスレッドをブロックし、単一 (ランダム) またはすべてのスレッドを起動します。
2. 実装メカニズムが異なります。 LockSuport はモニターのオブジェクト object を指定できますが、LockSuport と object.wait() のブロッキング キューは交差しません。テスト例をご覧いただけます。 object.notifyAll() は、LockSupport のブロックしているスレッドを起動できません。
質問 5: LockSupport.park(Object blocker) によって渡されるブロッカー オブジェクトは何に使用されますか?
回答: 対応する blcoker は Thread の parkBlocker 属性に記録されます。jstack コマンドを使用して特定のブロック オブジェクトを監視すると非常に便利です。
次のようにコードをコピーします。
public static void park(オブジェクトブロッカー) {
スレッド t = Thread.currentThread();
setBlocker(t, blocker); //Thread.parkBlocker プロパティの値を設定します。
unsafe.park(false, 0L);
setBlocker(t, null); // Thread.parkBlocker プロパティの値をクリアします。
}
次のようにコードをコピーします。
public static void park(オブジェクトブロッカー) {
スレッド t = Thread.currentThread();
setBlocker(t, blocker); //Thread.parkBlocker プロパティの値を設定します。
unsafe.park(false, 0L);
setBlocker(t, null); // Thread.parkBlocker プロパティの値をクリアします。
}
LockSupport の具体的な javadoc の説明も、以下で読むことができます。
質問 6: LockSupport は Thread.interrupt() イベントに応答できますか? InterruptedException がスローされるでしょうか?
回答: 割り込みイベントに応答できますが、InterruptedException はスローされません。 LockSupport の Thread.interrupte のサポートについては、javadoc の説明も参照してください。
関連するテストコード
次のようにコードをコピーします。
パッケージcom.agapple.cocurrent;
java.io.ファイルをインポートします。
java.io.FileInputStreamをインポートします。
java.lang.reflect.Fieldをインポートします。
java.util.concurrent.TimeUnitをインポートします。
インポート java.util.concurrent.locks.LockSupport;
パブリック クラス LockSupportTest {
private static LockSupportTest ブロッカー = new LockSupportTest();
public static void main(String args[]) throws Exception {
lockSupportTest();
parkTest();
中断パークテスト();
中断スリープテスト();
割り込み待機テスト();
}
/**
* LockSupport.park オブジェクトの後に、Thread.blocker オブジェクトを取得し、その 1 つのウェイクアップを呼び出します。
*
* @throwsException
*/
private static void lockSupportTest() が例外をスローする {
スレッド t = doTest(new TestCallBack() {
@オーバーライド
public void callback() が例外をスローする {
// 5秒スリープしてみる
System.out.println("ブロッカー");
LockSupport.park(ブロッカー);
System.out.println("今すぐ目覚めましょう!");
}
@オーバーライド
public String getName() {
"lockSupportTest" を返します。
}
});
t.start(); // 読み取りスレッドを開始します。
Thread.sleep(150);
同期化 (ブロッカー) {
フィールド field = Thread.class.getDeclaredField("parkBlocker");
フィールド.setAccessible(true);
オブジェクト fBlocker = フィールド.get(t);
System.out.println(blocker == fBlocker);
Thread.sleep(100);
System.out.println("notifyAll");
blocker.notifyAll();
}
}
/**
* object.wait() を中断しようとすると、対応する InterruptedException がスローされます。
*
* @throws 中断例外
*/
プライベート静的無効割り込みWaitTest()スローInterruptedException {
最終オブジェクト obj = 新しい Object();
スレッド t = doTest(new TestCallBack() {
@オーバーライド
public void callback() が例外をスローする {
// 5秒スリープしてみる
obj.wait();
System.out.println("今すぐ目覚めましょう!");
}
@オーバーライド
public String getName() {
"interruptWaitTest" を返します。
}
});
t.start(); // 読み取りスレッドを開始します。
Thread.sleep(2000);
t.interrupt(); // パーク中に割り込みが応答されたかどうかを確認します。
}
/**
* Thread.sleep() を中断しようとすると、対応する InterruptedException がスローされます。
*
* @throws 中断例外
*/
private static void中断SleepTest()スローInterruptedException {
スレッド t = doTest(new TestCallBack() {
@オーバーライド
public void callback() が例外をスローする {
// 5秒スリープしてみる
Thread.sleep(5000);
System.out.println("今すぐ目覚めましょう!");
}
@オーバーライド
public String getName() {
"interruptSleepTest" を返します。
}
});
t.start(); // 読み取りスレッドを開始します。
Thread.sleep(2000);
t.interrupt(); // パーク中に割り込みが応答されたかどうかを確認します。
}
/**
* LockSupport.park() を中断しようとすると、応答はありますが、InterruptedException 例外はスローされません
*
* @throws 中断例外
*/
private static void中断ParkTest() throws InterruptedException {
スレッド t = doTest(new TestCallBack() {
@オーバーライド
public void callback() {
//独自のスレッドをパークしてみます
LockSupport.parkNanos(ブロッカー、TimeUnit.SECONDS.toNanos(5));
System.out.println("今すぐ目覚めましょう!");
}
@オーバーライド
public String getName() {
「中断パークテスト」を返します;
}
});
t.start(); // 読み取りスレッドを開始します。
Thread.sleep(2000);
t.interrupt(); // パーク中に割り込みが応答されたかどうかを確認します。
}
/**
* LockSupport.unPark() を中断しようとすると、応答が返されます。
*
* @throws 中断例外
*/
private static void parkTest() が InterruptedException をスローする {
スレッド t = doTest(new TestCallBack() {
@オーバーライド
public void callback() {
//独自のスレッドをパークしてみます
LockSupport.park(ブロッカー);
System.out.println("今すぐ目覚めましょう!");
}
@オーバーライド
public String getName() {
「パークテスト」を返します。
}
});
t.start(); // 読み取りスレッドを開始します。
Thread.sleep(2000);
LockSupport.unpark(t);
t.interrupt();
}
public static Thread doTest(final TestCallBack call) {
新しいスレッドを返す() {
@オーバーライド
public void run() {
File file = new File("/dev/urandom"); // Linux ブラックホールを読み取る
試す {
FileInputStream in = 新しい FileInputStream(file);
byte[] バイト = 新しいバイト [1024];
while (in.read(bytes, 0, 1024) > 0) {
if (Thread.interrupted()) {
新しい InterruptedException("") をスローします。
}
System.out.println(bytes[0]);
Thread.sleep(100);
ロングスタート = System.currentTimeMillis();
call.callback();
System.out.println(call.getName() + " コールバック終了コスト : "
+ (System.currentTimeMillis() - start));
}
} catch (例外 e) {
e.printStackTrace();
}
}
};
}
}
インターフェイス TestCallBack {
public void callback() は例外をスローします。
public String getName();
}
次のようにコードをコピーします。
パッケージcom.agapple.cocurrent;
java.io.ファイルをインポートします。
java.io.FileInputStreamをインポートします。
java.lang.reflect.Fieldをインポートします。
java.util.concurrent.TimeUnitをインポートします。
インポート java.util.concurrent.locks.LockSupport;
パブリック クラス LockSupportTest {
private static LockSupportTest ブロッカー = new LockSupportTest();
public static void main(String args[]) throws Exception {
lockSupportTest();
parkTest();
中断パークテスト();
中断スリープテスト();
割り込み待機テスト();
}
/**
* LockSupport.park オブジェクトの後に、Thread.blocker オブジェクトを取得し、その 1 つのウェイクアップを呼び出します。
*
* @throwsException
*/
private static void lockSupportTest() が例外をスローする {
スレッド t = doTest(new TestCallBack() {
@オーバーライド
public void callback() が例外をスローする {
// 5秒スリープしてみる
System.out.println("ブロッカー");
LockSupport.park(ブロッカー);
System.out.println("今すぐ目覚めましょう!");
}
@オーバーライド
public String getName() {
"lockSupportTest" を返します。
}
});
t.start(); // 読み取りスレッドを開始します。
Thread.sleep(150);
同期化 (ブロッカー) {
フィールド field = Thread.class.getDeclaredField("parkBlocker");
フィールド.setAccessible(true);
オブジェクト fBlocker = フィールド.get(t);
System.out.println(blocker == fBlocker);
Thread.sleep(100);
System.out.println("notifyAll");
blocker.notifyAll();
}
}
/**
* object.wait() を中断しようとすると、対応する InterruptedException がスローされます。
*
* @throws 中断例外
*/
プライベート静的無効割り込みWaitTest()スローInterruptedException {
最終オブジェクト obj = 新しい Object();
スレッド t = doTest(new TestCallBack() {
@オーバーライド
public void callback() が例外をスローする {
// 5秒スリープしてみる
obj.wait();
System.out.println("今すぐ目覚めましょう!");
}
@オーバーライド
public String getName() {
"interruptWaitTest" を返します。
}
});
t.start(); // 読み取りスレッドを開始します。
Thread.sleep(2000);
t.interrupt(); // パーク中に割り込みが応答されたかどうかを確認します。
}
/**
* Thread.sleep() を中断しようとすると、対応する InterruptedException がスローされます。
*
* @throws 中断例外
*/
private static voidinterruptSleepTest() throws InterruptedException {
スレッド t = doTest(new TestCallBack() {
@オーバーライド
public void callback() が例外をスローする {
// 5秒スリープしてみる
Thread.sleep(5000);
System.out.println("今すぐ目覚めましょう!");
}
@オーバーライド
public String getName() {
"interruptSleepTest" を返します。
}
});
t.start(); // 読み取りスレッドを開始します。
Thread.sleep(2000);
t.interrupt(); // パーク中に割り込みが応答されたかどうかを確認します。
}
/**
* LockSupport.park() を中断しようとすると、応答はありますが、InterruptedException 例外はスローされません
*
* @throws 中断例外
*/
private static void中断ParkTest() throws InterruptedException {
スレッド t = doTest(new TestCallBack() {
@オーバーライド
public void callback() {
//独自のスレッドをパークしてみます
LockSupport.parkNanos(ブロッカー、TimeUnit.SECONDS.toNanos(5));
System.out.println("今すぐ目覚めましょう!");
}
@オーバーライド
public String getName() {
「中断パークテスト」を返します;
}
});
t.start(); // 読み取りスレッドを開始します。
Thread.sleep(2000);
t.interrupt(); // パーク中に割り込みが応答されたかどうかを確認します。
}
/**
* LockSupport.unPark() を中断しようとすると、応答が返されます。
*
* @throws 中断例外
*/
private static void parkTest() が InterruptedException をスローする {
スレッド t = doTest(new TestCallBack() {
@オーバーライド
public void callback() {
//独自のスレッドをパークしてみます
LockSupport.park(ブロッカー);
System.out.println("今すぐ目覚めましょう!");
}
@オーバーライド
public String getName() {
「パークテスト」を返します。
}
});
t.start(); // 読み取りスレッドを開始します。
Thread.sleep(2000);
LockSupport.unpark(t);
t.interrupt();
}
public static Thread doTest(final TestCallBack call) {
新しいスレッドを返す() {
@オーバーライド
public void run() {
File file = new File("/dev/urandom"); // Linux ブラックホールを読み取る
試す {
FileInputStream in = 新しい FileInputStream(ファイル);
byte[] バイト = 新しいバイト[1024];
while (in.read(bytes, 0, 1024) > 0) {
if (Thread.interrupted()) {
新しい InterruptedException("") をスローします。
}
System.out.println(bytes[0]);
Thread.sleep(100);
ロングスタート = System.currentTimeMillis();
call.callback();
System.out.println(call.getName() + " コールバック終了コスト : "
+ (System.currentTimeMillis() - start));
}
} catch (例外 e) {
e.printStackTrace();
}
}
};
}
}
インターフェイス TestCallBack {
public void callback() は例外をスローします。
public String getName();
}
最後に<BR>記事がどんどん長くなってきたので、みんなで議論するためにフォーラムに投稿しただけで、結局のところ、この記事では使用レベルのことについてのみ説明しており、運営側からの Thread の紹介はしていません。一部のメカニズムについては、この分野に精通した Daniumen が意見を表明することもできます。