java.lang.Thread.Stateを理解する:WAITING(パーキング)


90

最初に、本当にばかげた質問です、私はただ待っている「駐車」が何を意味するのか疑問に思っていましたか?スレッドはパークされるのを待っていますか、それともパークされたばかりなので待機状態ですか?そして、そのパーキングが発生すると、どのくらいのCP​​U /メモリリソースが使用されますか?スレッドを駐車する目的は何ですか?

次に、JavaスレッドAPIのparkメソッドを確認します。

許可が利用可能でない限り、スレッドスケジューリングの目的で現在のスレッドを無効にします。

許可証が利用可能な場合、それは消費され、通話はすぐに戻ります。それ以外の場合、現在のスレッドはスレッドスケジューリングの目的で無効になり、3つのいずれかが発生するまで休止状態になります。

英語は私の母国語ではないので、私は「許可」を「スレッドを駐車する許可」の一種として意図していたことを理解するのが難しいので、次の質問があります。

  • その意味は何ですか、「許可」とは何ですか、そして誰がどのようにそれらの許可をチェックしていますか?
  • それはどういう意味ですか:「許可が利用可能である場合、それは消費されます」、それは「駐車」されていますか?
  • 続いて、2番目のポイントが真の場合、「駐車」と「休眠」の違いは何ですか?許可があれば永久に駐車でき、許可がなければ「休眠」にすることができますか?

ありがとう

回答:


36

許可とは、実行を継続する許可を意味します。駐車とは、許可が得られるまで実行を一時停止することを意味します。

Semaphoreの許可とは異なり、の許可はLockSupportスレッドに関連付けられ(つまり、許可は特定のスレッドに与えられます)、蓄積されません(つまり、スレッドごとに1つの許可しか存在できず、スレッドが許可を消費すると、許可は消えます)。

を呼び出すことにより、スレッドに許可を与えることができますunpark()。スレッドは、を呼び出すことにより、許可が使用可能になるまで(または、スレッドが中断されるか、タイムアウトが期限切れになるなど)、実行を一時停止できますpark()。許可が利用可能になると、パークされたスレッドはそれを消費し、park()メソッドを終了します。


2
したがって、スレッドAがスレッドBに対して「park」を呼び出したが、許可が利用可能である場合、つまり「Bをパークできない」場合、Aによって行われた呼び出しはただ戻り、Bはパークされません。そうでなければ、許可が利用できないとき、Bは従わなければなりません。それで、待機(駐車)は「私が許可を持っていないのでAが私を駐車しようとしているが、私は今それをすることができないので私もAをブロックしている」という意味ですか?この長い文章でごめんなさい。この待機はかなりのリソースを消費すると思います。許可証全体を誰が管理しているのか、まだ疑問に思っています。一部のスレッドには許可があり、他のスレッドには許可がないと誰が/何が決定しているのか。
レオナルド

2
@Leonardo:スレッドはそれ自体をパークすることしかできず、他のスレッドをパークする方法はありません。つまり、呼び出すとpark()は、「他のスレッドが呼び出すことで許可を得るまで、実行を一時停止したい」という意味ですunpark()
axtavt 2011

したがって、スレッドは他のスレッドをパークできませんが、他のスレッドによってパーク解除できますか?あれは正しいですか ?それで、その駐車はいつ起こりますか?たぶん、スレッドは現時点で行うべき仕事がありません、そしてそれはその許可を絶えず見ることによってそれをチェックする方法ですか?これは、たとえばデーモンスレッドに適しています。
レオナルド

また、WAITING(parking)とは、駐車を待機していることを意味しますか、それとも駐車後に待機状態にあることを意味しますか?申し訳ありませんが、これはばかげた質問です:-)
Leonardo

3
@レオナルド:駐車後の待機状態を意味します。
axtavt 2011

11

Javaスレッド状態のドキュメントによると、スレッドは次の3つの理由で待機状態になる可能性があります。

  1. タイムアウトなしのObject.wait
  2. タイムアウトなしのThread.join
  3. LockSupport.park

スレッドでparkメソッドを呼び出すと、許可がない限り、スレッドのスケジューリングのためにスレッドが無効になります。unparkメソッドを呼び出して、指定されたスレッドの許可がまだ利用できない場合は、利用できるようにすることができます。

したがって、スレッドがLockSupport.parkによって待機モードになっていると、待機(パーキング)として表示されます。

現在のスレッドでのみパークを呼び出すことができることに注意してください。これは、生産者/消費者デザインパターンを実装するのに非常に役立つメカニズムです。


3

許可を説明するクラスの説明(LockSupport javadocの上部)から:

このクラスは、それを使用する各スレッド、つまり許可(Semaphoreクラスの意味で)に関連付けられます。許可証が利用可能になると、パークへの呼び出しはすぐに戻り、その過程で[許可証]を消費します。そうしないと、[パークへの呼び出し]がブロックされる可能性があります。まだ利用できない場合は、パーク解除を呼び出すと許可が利用可能になります。(ただし、セマフォとは異なり、許可は蓄積されません。最大で1つしかありません。)

(英語を話さない人でも読みやすいように[テキスト]を拡張しました。)

うまくいけば、より深い理解を持つ誰かがこれについて詳しく説明することができます。axtavtの回答を参照してください。

最後に、javadocからの最後の引用:

これらのメソッドは、高レベルの同期ユーティリティを作成するためのツールとして使用するように設計されており、それ自体はほとんどの同時実行制御アプリケーションには役立ちません。


3

ドキュメントを読んでいる間、私が回避できなかったこの質問を再訪させた部分は、次のとおりでした。

許可証が利用できる場合、それは消費され、通話はすぐに戻ります...

だから、とき許可証は、「利用可能」で、誰どのようにそれがすぐに消費されます。できそうということ、それは可能なのでしょうか?これを見つけるのはどういうわけか簡単でした:

public static void main(String[] args) {

    Thread parkingThread = new Thread(() -> {
        System.out.println("Will go to sleep...");
        sleepTwoSeconds();
        System.out.println("Parking...");
        // this call will return immediately since we have called  LockSupport::unpark
        // before this method is getting called, making the permit available
        LockSupport.park();
        System.out.println("After parking...");
    });

    parkingThread.start();

    // hopefully this 1 second is enough for "parkingThread" to start
    // _before_ we call un-park
    sleepOneSecond();
    System.out.println("Un-parking...");
    // making the permit available while the thread is running and has not yet
    // taken this permit, thus "LockSupport.park" will return immediately
    LockSupport.unpark(parkingThread);

}

private static void sleepTwoSeconds() {
    try {
        Thread.sleep(1000 * 2);
    } catch (InterruptedException e) {
        e.printStackTrace();
    }
}

private static void sleepOneSecond() {
    try {
        Thread.sleep(1000);
    } catch (InterruptedException e) {
        e.printStackTrace();
    }
}    

コードはそれ自体を語り、thread実行中ですがまだ呼び出されていませんLockSupport.park、他のスレッドがLockSupport.unparkそれを呼び出しています-したがって、許可が利用可能になります。その後、電話をかけLockSupport.park、許可証が利用可能になるとすぐに戻ります。

あなたはそれについて考えるたら、あなたがコントロールしていないいくつかのコードとそのコードの呼び出しに自分のスレッドを公開する場合、これは、少し危険ですLockSupport.unparkあなたしばらくparkその後-それは動作しない場合があります。


非常に良い点ですが、許可を与えるアクティビティ(つまり、unpark()の呼び出し)は、スレッドがパークされている場合にのみ関連すると思いました。
アルフレッドシャオ

@AlfredXiaoは同意しました、これも私を驚かせたものですが、それはある意味理にかなっていると思います。
ユージーン

1

私が理解しているように、「許可」は、スレッドを「パーク解除」できるかどうかを表す単なるオブジェクトです。そして、これはスレッド自体(またはスレッドをパークしようとするとde JRE)によってチェックされます。「消費された」こと、許可が消え、スレッドが無効にされないことを理解しています。

マルチスレッドについてもう少し学ぶ必要があると思います。「許可」と呼ばれるオブジェクトを備えたディスペンサーと考えてください。あなたはスレッドに駐車するように言い、スレッドはディスペンサーをチェックします。「許可」がある場合、スレッドはそれを取り去ります(駐車なし)。ディスペンサーに「許可」がない場合、「許可」が使用可能になるまでスレッドは保留されます(そして、unpark。を使用してディスペンサーに「許可」を入れることができます。

CPU /メモリ使用量は、OSなどによると思います。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.