ホームページ Java &#&チュートリアル Java スレッドのステータスがブロックされました

Java スレッドのステータスがブロックされました

Nov 22, 2016 pm 04:20 PM
java

BLOCKED 状態の定義

前に述べたように、BLOCKED の簡単な定義は次のとおりです:

モニター ロックを待ってブロックされているスレッドは、この状態にあります。 (モニターのロックを待ってブロックされたスレッドはこの状態になります。)

より詳細な定義については、Thread.State の javadoc を参照してください:

/**
         * Thread state for a thread blocked waiting for a monitor lock.
         * A thread in the blocked state is waiting for a monitor lock
         * to enter a synchronized block/method or
         * reenter a synchronized block/method after calling
         * {@link Object#wait() Object.wait}.
         */
        BLOCKED,
ログイン後にコピー

この文は非常に長いので、2 つの単純な文に分けることができます。理解できる文章。

ブロック状態のスレッドは、同期されたブロック/メソッドに入るモニターロックを待っています。

ブロック状態のスレッドは、同期されたブロックまたはメソッドに入るモニター ロックを待っています。

ブロック状態のスレッドは、Object.wait を呼び出した後、同期されたブロック/メソッドに再度入るためにモニター ロックを待機しています。

ブロック状態のスレッドは、同期されたブロックまたはメソッドに再度入るために Object.wait メソッドを呼び出した後、モニターのロックを待機しています。

同期ブロックに入る(入力する)ときにブロックする

まず最初の文について話します、これは理解しやすいです。

モニターロックは、複数のスレッド間の相互排他を実現するための同期アクセスに使用されます。したがって、スレッドがロックを取得して同期ブロックに入ると、それが外に出る前に、他のスレッドが入ろうとすると、ロックを取得できないため、同期ブロックの外でブロックされます。この時点では、状態は BLOCKED になります。

注: この状態の開始と終了は私たちの制御下にはありません。ロックが使用可能になると、スレッドはブロック状態から回復します。

このプロセスを示すためにいくつかのコードを使用できます:

@Test
public void testBlocked() throws Exception {
    class Counter {
        int counter;
        public synchronized void increase() {
            counter++;
            try {
                Thread.sleep(30000);
            } catch (InterruptedException e) {
                throw new RuntimeException(e);
            }
        }
    }
    
    Counter c = new Counter();
    
    Thread t1 = new Thread(new Runnable() {
        public void run() {
            c.increase();
        }
    }, "t1线程");
    t1.start();
    
    Thread t2 = new Thread(new Runnable() {
        public void run() {
            c.increase();
        }
    }, "t2线程");
    t2.start();
    
    Thread.sleep(100); // 确保 t2 run已经得到执行
    assertThat(t2.getState()).isEqualTo(Thread.State.BLOCKED);
}
ログイン後にコピー

上記は、同期増加メソッドを使用してアクセス カウンター カウンターを定義しています。 t1 スレッドが最初に入力し、その後同期ブロックでスリープしたため、ロックが遅延しました。t2 が同期メソッドを実行しようとしたときに、ロックを取得できなかったためブロックされました。

VisualVM モニタリングは、t2 スレッドのステータスを示します。

Java スレッドのステータスがブロックされました

画像の「モニター」ステータスは、BLOCKED ステータスです。 t1 のスリープ中、t2 は BLOCKED 状態にあることがわかります。

BLOCKED 状態は、特別な種類の WAITING、特にロックを待機しているとみなすことができます。

同期ブロックに再入するときにブロックを待機します

次に 2 番目の文をもう一度見てください:

2. ブロックされた状態のスレッドは、Object wait を呼び出した後、同期ブロック/メソッドに再入するためにモニター ロックを待機しています。

ブロック状態のスレッドは、同期されたブロックまたはメソッドに再度入るために Object.wait メソッドを呼び出した後、モニターのロックを待機しています。

この文は少し複雑で、簡潔な中国語の文に翻訳するのは簡単ではありません。 wait に関連する背景をよく理解していないと、この文を理解するのは簡単ではありません。ここで少し詳しく説明してみましょう。再入力なので、2 回入力することになります。

wait メソッドの呼び出しは同期ブロック内にある必要があります。つまり、最初にロックを取得して同期ブロックに入る必要があります。入力。

waitを呼び出した後、ロックは解放され、このロックの待機キュー(wait set)に入れられます。

他のスレッドからnotifyまたはnotifyAll通知を受信した後、待機中のスレッドはすぐに実行を再開できません。これは、停止が同期ブロック内にあり、ロックが解放されているためです。そのため、再入力(reenter)する前にロックを再取得する必要があります。ブロックを同期し、その後、最後の待機ポイントから実行を再開します。 2回目の入場なので再入場といいます。

ただし、最初にロックが与えられるわけではありません。このプロセスは、実際には Enter プロセスと同じなので、ロックが占有されているために BLOCKED が発生する可能性もあります。他のスレッド。

このプロセスは、Object.wait を呼び出した後、同期されたブロック/メソッドを再入力すると呼ばれます。

このプロセスを示すためにコードの一部も使用します:

@Test
public void testReenterBlocked() throws Exception {
    class Account {
        int amount = 100; // 账户初始100元
        public synchronized void deposit(int cash) { // 存钱
            amount += cash;
            notify();
            try {
                Thread.sleep(30000); // 通知后却暂时不退出
            } catch (InterruptedException e) {
                throw new RuntimeException(e);
            }
        }
        public synchronized void withdraw(int cash) { // 取钱
            while (cash > amount) {
                try {
                    wait();
                } catch (InterruptedException e) {
                    throw new RuntimeException(e);
                }
            }
            amount -= cash;
        }
    }
    Account account = new Account();
    
    Thread withdrawThread = new Thread(new Runnable() {
        public void run() {
            account.withdraw(200);
        }
    }, "取钱线程");
    withdrawThread.start();
    
    Thread.sleep(100); // 确保取钱线程已经得到执行
    
    assertThat(withdrawThread.getState()).isEqualTo(Thread.State.WAITING);
    
    Thread depositThread = new Thread(new Runnable() {
        public void run() {
            account.deposit(100);
        }
    }, "存钱线程");
    Thread.sleep(10000); // 让取钱线程等待一段时间
    depositThread.start();

    Thread.sleep(300); // 确保取钱线程已经被存钱线程所通知到

    assertThat(withdrawThread.getState()).isEqualTo(Thread.State.BLOCKED);
}
ログイン後にコピー

上記のコード シナリオの簡単な紹介:

入金メソッドと出金メソッドを持つアカウント オブジェクトがあり、初期金額は 100 元です。

お金の引き出しスレッドが最初に開始され、同期ブロックに入ります。お金が足りないことが判明すると、waitが呼び出され、ロックが解除され、スレッドがハングします。州)。

入金スレッドは 10 秒後に開始され、お金を入金して出金スレッドに通知しますが、その後同期ブロック内でスリープし続けるため、ロックが解放されません。

通知を受け取った後、出金スレッドは待機状態を抜けますが、ロックを保持していません。実行を再開するために同期ブロックに再入しようとすると、デポジットスレッドによってロックが解放されていないため、ブロックされます(BLOCKED)。州) )。

監視対象ディスプレイ:

Java スレッドのステータスがブロックされました

図に示すように、出金スレッドは最初はWAITINGであり、通知を受け取った後にロックを取得できないためブロック(BLOCKED)されます。

まとめ

この 2 つの文を一緒に見ると 2 つの意味がありますが、簡単に言うと Enter、reenter、または Enter という意味になります。ブロックを取得できない場合、スレッドは BLOCKED 状態になります。

スレッドが長時間 BLOCKED 状態にある場合は、デッドロックが発生していないかどうかを検討してください。

BLOCKED 状態は、従来の待機状態をさらに細分化した特別な種類の待機とみなすことができます。

Java スレッドのステータスがブロックされました WAITING 状態についてはまだ言及されておらず、ここでは wait メソッドが関係しているため、待機は次のようになります。これも上で少し説明しましたが、いくつかの分析を行った後、次の章で WAITING と TIMED_WAITING の 2 つの状態をより詳細に分析します。

このウェブサイトの声明
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。

ホットAIツール

Undresser.AI Undress

Undresser.AI Undress

リアルなヌード写真を作成する AI 搭載アプリ

AI Clothes Remover

AI Clothes Remover

写真から衣服を削除するオンライン AI ツール。

Undress AI Tool

Undress AI Tool

脱衣画像を無料で

Clothoff.io

Clothoff.io

AI衣類リムーバー

AI Hentai Generator

AI Hentai Generator

AIヘンタイを無料で生成します。

ホットツール

メモ帳++7.3.1

メモ帳++7.3.1

使いやすく無料のコードエディター

SublimeText3 中国語版

SublimeText3 中国語版

中国語版、とても使いやすい

ゼンドスタジオ 13.0.1

ゼンドスタジオ 13.0.1

強力な PHP 統合開発環境

ドリームウィーバー CS6

ドリームウィーバー CS6

ビジュアル Web 開発ツール

SublimeText3 Mac版

SublimeText3 Mac版

神レベルのコード編集ソフト(SublimeText3)

Javaの平方根 Javaの平方根 Aug 30, 2024 pm 04:26 PM

Java の平方根のガイド。ここでは、Java で平方根がどのように機能するかを、例とそのコード実装をそれぞれ示して説明します。

Javaの完全数 Javaの完全数 Aug 30, 2024 pm 04:28 PM

Java における完全数のガイド。ここでは、定義、Java で完全数を確認する方法、コード実装の例について説明します。

Javaのアームストロング数 Javaのアームストロング数 Aug 30, 2024 pm 04:26 PM

Java のアームストロング番号に関するガイド。ここでは、Java でのアームストロング数の概要とコードの一部について説明します。

Java の乱数ジェネレーター Java の乱数ジェネレーター Aug 30, 2024 pm 04:27 PM

Java の乱数ジェネレーターのガイド。ここでは、Java の関数について例を挙げて説明し、2 つの異なるジェネレーターについて例を挙げて説明します。

ジャワのウェカ ジャワのウェカ Aug 30, 2024 pm 04:28 PM

Java の Weka へのガイド。ここでは、weka java の概要、使い方、プラットフォームの種類、利点について例を交えて説明します。

Javaのスミス番号 Javaのスミス番号 Aug 30, 2024 pm 04:28 PM

Java のスミス番号のガイド。ここでは定義、Java でスミス番号を確認する方法について説明します。コード実装の例。

Java Springのインタビューの質問 Java Springのインタビューの質問 Aug 30, 2024 pm 04:29 PM

この記事では、Java Spring の面接で最もよく聞かれる質問とその詳細な回答をまとめました。面接を突破できるように。

Java 8 Stream Foreachから休憩または戻ってきますか? Java 8 Stream Foreachから休憩または戻ってきますか? Feb 07, 2025 pm 12:09 PM

Java 8は、Stream APIを導入し、データ収集を処理する強力で表現力のある方法を提供します。ただし、ストリームを使用する際の一般的な質問は次のとおりです。 従来のループにより、早期の中断やリターンが可能になりますが、StreamのForeachメソッドはこの方法を直接サポートしていません。この記事では、理由を説明し、ストリーム処理システムに早期終了を実装するための代替方法を調査します。 さらに読み取り:JavaストリームAPIの改善 ストリームを理解してください Foreachメソッドは、ストリーム内の各要素で1つの操作を実行する端末操作です。その設計意図はです

See all articles