検索
ホームページJava&#&チュートリアルJavaでスレッド間の通信を実装するためにwaitとnotifyを使用する方法

    1. スレッド通信が必要な理由

    スレッドは同時に実行され、これはスレッドのランダムな実行のように見えますが、実際のアプリケーションではスレッドを使用します。通信 実行順序が必要なので、スレッド通信を使用する必要があります。

    スレッド通信 スレッドの実行順序を解決するために優先順位を使用してみてはいかがでしょうか?

    全体の優先度は、スレッド PCB 内の優先度情報とスレッドの待機時間によって決定されるため、一般的な開発では、スレッドの実行順序を示すために優先度に依存することはありません。

    参照以下のようなシーン: 生産者と消費者モデルを説明するためのパン屋の例

    生産者と消費者に対応する、パン屋と顧客がいるパン屋があります。パン屋にはパンを保管するための在庫があります。在庫がいっぱいになると、生産されなくなります。同時に、消費者はパンも購入します。パンの在庫が売り切れると、消費者は引き続き購入する前に、新しいパンが生産されるまで待たなければなりません

    分析: いつ生産を停止し、いつ消費を停止するかについて、生産と消費の情報を正確に伝えるためにスレッド通信を適用する必要があります

    2. 待機メソッドと通知メソッド

    wait() : 現在のスレッドによって保持されているオブジェクトを許可します。 ロックを解放して待機します。

    wait(long timeout): 対応するパラメータは、スレッドが待機する時間です。

    notify(): スレッドを起動します。同じオブジェクトを使用して wait を呼び出し、待機中のスレッドに入り、再度オブジェクト ロックを競合します。

    notifyAll(): 複数のスレッドが待機している場合、notifyAll はすべてのスレッドを起動し、notify はランダムに 1 つを起動します

    注:

    これらのメソッドはすべて、オブジェクト クラスのメソッドに属します。

    同期された同期コード ブロック/同期メソッドで使用する必要があります

    どのオブジェクトがロックされているかは、wait と notify に使用されるオブジェクトです。

    notify 直後に起動せず、同期が完了するまで待ってから起動します。

    1 .wait() メソッド

    wait メソッドの呼び出し後:

    現在のコードを実行しているスレッドを待機させます (スレッドは待機キューに入れられます)

    現在のロックを解放します

    特定の条件が満たされると起動し、再度ロックの取得を試みます

    待機終了の条件:

    他のスレッドがオブジェクトのnotifyメソッドを呼び出す

    wait待機時間タイムアウト(待ち時間を指定するタイムアウトパラメータ)

    他のスレッドが割り込みメソッドを呼び出すとwaitがInterruptedExceptionをスローする

    2. Notice() メソッド

    ##パラメータなしで wait メソッドを使用する場合は、notify メソッドを使用してスレッドをウェイクアップして待機する必要があります

    このメソッドはウェイクアップするためのものですオブジェクトのオブジェクト ロックを待機しているスレッドを起動して、オブジェクトのオブジェクト ロックを再取得できるようにします。

    待機中のスレッドが複数ある場合、スレッド スケジューラは待機ステータス スレッドをランダムに選択します (最初のスレッドはありません)。 -come, first-served)

    notify() メソッドの後、現在のスレッドはオブジェクト ロックをすぐに解放せず、notify() メソッドを実行しているスレッドがプログラムの実行を終了するまで待機します。 、同期コードを終了します オブジェクトのロックは、ブロックの後でのみ解放されます

    3.notifyAll() メソッド

    このメソッドは、起動時を除き、notify() メソッドと同じ効果があります。起動すると、待機中のすべてのスレッドが起動されます

    notify() メソッドはランダムにスレッドを起動するだけです

    3. wait と Notice を使用してベーカリー ビジネスを実装します

    前提条件:

    はい 2 人のパン屋がいます。パン屋は一度に 2 つのパンを作ることができます。

    倉庫には 100 のパンを保管できます。

    消費者は 10 人いて、各消費者は 1 つずつ購入します

    注:

    消費と生産は同時に並行して実行され、1 つの生産と 1 つの消費ではありません。 #実装コード:

    public class Bakery {
        private static int total;//库存
     
        public static void main(String[] args) {
            Producer producer = new Producer();
            for(int i = 0;i < 2;i++){
                new Thread(producer,"面包师傅-"+(i-1)).start();
            }
            Consumer consumer = new Consumer();
            for(int i = 0;i < 10;i++){
                new Thread(consumer,"消费者-"+(i-1)).start();
            }
        }
        private static class Producer implements Runnable{
            private int num = 3; //生产者每次生产三个面包
            @Override
            public void run() {
                try {
                    while(true){ //一直生产
                        synchronized (Bakery.class){
                            while((total+num)>100){ //仓库满了,生产者等待
                                Bakery.class.wait();
                            }
                            //等待解除
                            total += num;
                            System.out.println(Thread.currentThread().getName()+"生产面包,库存:"+total);
                            Thread.sleep(500);
                            Bakery.class.notifyAll(); //唤醒生产
                        }
                        Thread.sleep(500);
                    }
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }
        private static class Consumer implements Runnable{
            private int num = 1; //消费者每次消费1个面包
            @Override
            public void run() {
                try {
                    while(true){ //一直消费
                        synchronized (Bakery.class){
                            while((total-num)<0){ //仓库空了,消费者等待
                                Bakery.class.wait();
                            }
                            //解除消费者等待
                            total -= num;
                            System.out.println(Thread.currentThread().getName()+"消费面包,库存:"+total);
                            Thread.sleep(500);
                            Bakery.class.notifyAll(); //唤醒消费
                        }
                        Thread.sleep(500);
                    }
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }
    }

    部分的な印刷結果:

    4. ブロッキング キュー

    Javaでスレッド間の通信を実装するためにwaitとnotifyを使用する方法ブロッキング キューは特殊なキューです。これも「先入れ先出し」の原則に従っており、スレッドセーフなキュー構造です。

    特徴: 典型的な生産者/消費者モデルで、一般にタスクの分離とピーク削減に使用されます

    キューがいっぱいの場合、キューはブロックされて待機します (実稼働)、他のスレッドがキューから要素を取得するまで

    キューが空の場合、キューはブロックされて待機します (消費)、他のスレッドが要素を挿入するまで待機します

    1. プロデューサー コンシューマー モデル


    プロデューサー/コンシューマー モデルは、コンテナーを使用して、プロデューサーとコンシューマー間の強い結合の問題を解決します。

    プロデューサーとコンシューマーは、次のことを行います。相互に直接通信するのではなく、ブロッキングを介して通信します キューは通信に使用されるため、プロデューサーがデータを生成した後、コンシューマーがデータを処理するのを待って、それをブロッキング キューに直接スローします。コンシューマーはプロデューサーに要求しません。

    ブロッキング キューは、バッファ内でプロデューサーとコンシューマの処理能力のバランスをとります。

    ブロッキング キューは、プロデューサーとコンシューマを分離することもできます

    上記のベーカリー ビジネスの実装は生産者消費者モデルです。 例


    2. 標準ライブラリのブロッキング キュー

    ブロッキング キューは Java 標準ライブラリに組み込まれています。一部のプログラムではブロッキング キューを使用する必要がありますが、標準ライブラリではブロッキング キューを直接使用する必要があります。

    BlockingQueue 是一个接口. 真正实现的类是 LinkedBlockingQueue

    put 方法用于阻塞式的入队列, take 用于阻塞式的出队列

    BlockingQueue 也有 offer, poll, peek 等方法, 但是这些方法不带有阻塞特性

            BlockingDeque<String> queue = new LinkedBlockingDeque<>();
            queue.put("hello");
            //如果队列为空,直接出出队列就会阻塞
            String ret = queue.take();
            System.out.println(ret);

    3. 阻塞队列的模拟实现

    这里使用数组实现一个循环队列来模拟阻塞队列

    当队列为空的时候,就不能取元素了,就进入wait等待,当有元素存放时,唤醒

    当队列为满的时候,就不能存元素了,就进入wait等待,当铀元素取出时,唤醒 

    实现代码:

    public class MyBlockingQueue {
        //使用数组实现一个循环队列,队列里面存放的是线程要执行的任务
        private Runnable[] tasks;
        //队列中任务的数量,根据数量来判断是否可以存取
        private int count;
        private int putIndex; //存放任务位置
        private int takeIndex; //取出任务位置
     
        //有参的构造方法,表示队列容量
        public MyBlockingQueue(int size){
            tasks = new Runnable[size];
        }
     
        //存任务
        public void put(Runnable task){
            try {
                synchronized (MyBlockingQueue.class){
                    //如果队列容量满了,则存任务等待
                    while(count == tasks.length){
                        MyBlockingQueue.class.wait();
                    }
                    tasks[putIndex] = task; //将任务放入数组
                    putIndex = (putIndex+1) % tasks.length; //更新存任务位置
                    count++; //更新存放数量
                    MyBlockingQueue.class.notifyAll(); //唤醒存任务
                }
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
     
        //取任务
        public Runnable take(){
            try {
                synchronized (MyBlockingQueue.class){
                    //如果队列任务为空,则取任务等待
                    while(count==0){
                        MyBlockingQueue.class.wait();
                    }
                    //取任务
                    Runnable task = tasks[takeIndex];
                    takeIndex = (takeIndex+1) % tasks.length; //更新取任务位置
                    count--; //更新存放数量
                    MyBlockingQueue.class.notifyAll(); //唤醒取任务
                    return task;
                }
            } catch (InterruptedException e) {
               throw new RuntimeException("存放任务出错",e);
            }
        }
    }

    五. wait和sleep的区别(面试题)

    相同点:

    都可以让线程放弃执行一段时间 

    不同点:

    ☘️wait用于线程通信,让线程在等待队列中等待

    ☘️sleep让线程阻塞一段时间,阻塞在阻塞队列中

    ☘️wait需要搭配synchronized使用,sleep不用搭配

    ☘️wait是Object类的方法,sleep是Thread的静态方法

    以上がJavaでスレッド間の通信を実装するためにwaitとnotifyを使用する方法の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

    声明
    この記事は亿速云で複製されています。侵害がある場合は、admin@php.cn までご連絡ください。
    JVMパフォーマンスと他の言語JVMパフォーマンスと他の言語May 14, 2025 am 12:16 AM

    jvm'sperformanceiscompetitivewitherruntimes、sped、safety、andproductivityの提供

    Javaプラットフォームの独立性:使用の例Javaプラットフォームの独立性:使用の例May 14, 2025 am 12:14 AM

    javaachievesplatformedentenceTheThejavavirtualMachine(JVM)、avainwithcodetorunonanyplatformwithajvm.1)codescompiledintobytecode、notmachine-specificcode.2)

    JVMアーキテクチャ:Java Virtual Machineに深く飛び込みますJVMアーキテクチャ:Java Virtual Machineに深く飛び込みますMay 14, 2025 am 12:12 AM

    thejvmisanabstractcomputingMachineCrucialForrunningJavaProgramsDuetoitsPlatForm-IndopentInterChitecture.Itincludes:1)ClassLoaderForloadingClasses、2)Runtimedataareaforforforatastorage、3)executionEngineWithinterter、Jitcompiler、およびGarbagecolfecolfecolfececolfecolfer

    JVM:JVMはOSに関連していますか?JVM:JVMはOSに関連していますか?May 14, 2025 am 12:11 AM

    jvmhasacloserelationshiptheosasittrantesjavabytecodecodecodecodecodecodecodecodecodecodecodecodecodetructions、manageSmemory、およびhandlesgarbagecollection.thisrelationshipallowsjavatorunonvariousosenvirnments、Butalsedentsはspeedifediferentjvmbeviorhiorsandosendisfredediferentjvmbehbehioorysando

    Java:一度書く、どこでも実行(wora) - プラットフォームの独立に深く潜るJava:一度書く、どこでも実行(wora) - プラットフォームの独立に深く潜るMay 14, 2025 am 12:05 AM

    Javaの実装「Write and、Run Everywherewhere」はBytecodeにコンパイルされ、Java仮想マシン(JVM)で実行されます。 1)Javaコードを書き、それをByteCodeにコンパイルします。 2)JVMがインストールされたプラットフォームでByteCodeが実行されます。 3)Javaネイティブインターフェイス(JNI)を使用して、プラットフォーム固有の機能を処理します。 JVMの一貫性やプラットフォーム固有のライブラリの使用などの課題にもかかわらず、Woraは開発効率と展開の柔軟性を大幅に向上させます。

    Javaプラットフォームの独立性:異なるOSとの互換性Javaプラットフォームの独立性:異なるOSとの互換性May 13, 2025 am 12:11 AM

    javaachievesplatformentenceTheTheTheJavavirtualMachine(JVM)、CodetorunondifferentoperatingSystemswithOutModification.thejvmcompilesjavacodeplatform-IndopentedbyTecodeを承認することを許可します

    Javaをまだ強力にしている機能Javaをまだ強力にしている機能May 13, 2025 am 12:05 AM

    javaispowerfulfulduetoitsplatformindepentence、object-orientednature、richstandardlibrary、performancecapability、andstrongsecurityfeatures.1)platformendependenceallowseplicationStorunonaydevicesupportingjava.2)オブジェクト指向のプログラマン型

    トップJava機能:開発者向けの包括的なガイドトップJava機能:開発者向けの包括的なガイドMay 13, 2025 am 12:04 AM

    上位のJava関数には、次のものが含まれます。1)オブジェクト指向プログラミング、サポートポリ型、コードの柔軟性と保守性の向上。 2)例外処理メカニズム、トライキャッチ式ブロックによるコードの堅牢性の向上。 3)ゴミ収集、メモリ管理の簡素化。 4)ジェネリック、タイプの安全性の向上。 5)コードをより簡潔で表現力豊かにするためのAMBDAの表現と機能的なプログラミング。 6)最適化されたデータ構造とアルゴリズムを提供するリッチ標準ライブラリ。

    See all articles

    ホット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衣類リムーバー

    Video Face Swap

    Video Face Swap

    完全無料の AI 顔交換ツールを使用して、あらゆるビデオの顔を簡単に交換できます。

    ホットツール

    SAP NetWeaver Server Adapter for Eclipse

    SAP NetWeaver Server Adapter for Eclipse

    Eclipse を SAP NetWeaver アプリケーション サーバーと統合します。

    MinGW - Minimalist GNU for Windows

    MinGW - Minimalist GNU for Windows

    このプロジェクトは osdn.net/projects/mingw に移行中です。引き続きそこでフォローしていただけます。 MinGW: GNU Compiler Collection (GCC) のネイティブ Windows ポートであり、ネイティブ Windows アプリケーションを構築するための自由に配布可能なインポート ライブラリとヘッダー ファイルであり、C99 機能をサポートする MSVC ランタイムの拡張機能が含まれています。すべての MinGW ソフトウェアは 64 ビット Windows プラットフォームで実行できます。

    ゼンドスタジオ 13.0.1

    ゼンドスタジオ 13.0.1

    強力な PHP 統合開発環境

    ZendStudio 13.5.1 Mac

    ZendStudio 13.5.1 Mac

    強力な PHP 統合開発環境

    mPDF

    mPDF

    mPDF は、UTF-8 でエンコードされた HTML から PDF ファイルを生成できる PHP ライブラリです。オリジナルの作者である Ian Back は、Web サイトから「オンザフライ」で PDF ファイルを出力し、さまざまな言語を処理するために mPDF を作成しました。 HTML2FPDF などのオリジナルのスクリプトよりも遅く、Unicode フォントを使用すると生成されるファイルが大きくなりますが、CSS スタイルなどをサポートし、多くの機能強化が施されています。 RTL (アラビア語とヘブライ語) や CJK (中国語、日本語、韓国語) を含むほぼすべての言語をサポートします。ネストされたブロックレベル要素 (P、DIV など) をサポートします。