Javaマルチスレッド学習---wait()、notify/notifyAll()の使用

4442 ワード

マルチスレッドのいくつかの状態
新規作成         準備完了         うんてん         ブロッキング         死ぬ
  • 新規:スレッドが作成された
  • 準備完了:CPUの実行資格を有するが、CPUの実行権を持たない
  • .
  • 運転:CPUの実行資格を有する、CPUの実行権も有する
  • .
  • ブロック:CPUの実行資格もCPUの実行権もない
  • .
  • 死亡:CPUの実行資格もCPUの実行権もない
  • .
    スレッドのブロック状態
    前回sleepはスレッドをブロック状態にすることができると述べましたが、今日お話しするwait()メソッドはスレッドをブロック状態にすることもできます.まず、この2つの方法の違いを見てみましょう.
  • 共通点:wait()メソッドとsleep()メソッドは、スレッドをブロック状態にする、スレッドのブロック時間
  • を設定することができる.
  • 異なる点:wait()は時間量を設定してもよいし、設定しなくてもよい.sleep()は、スリープ時間wait()を設定するためにロックを取得する必要があり、synchronizedキーワードと組み合わせて使用されるのが一般的である.すなわち、synchronized同期コードブロックでwait()、notify/notifyAll()メソッドを使用するのが一般的である.sleep()は必ずしもロックを取得する必要はありません.sleep()スリープロックwait()は、待機するとロックを解放せず、notify/notifyAll()が実行されるまでcpuの実行権を呼び出し、
  • を実行し続ける.
    wait()ブロック状態の起動
    スレッドがwait()メソッドを実行すると、現在のロックが解放され、CPUが呼び出され、待機状態になります.notify/notifyAll()が実行されると、synchronizedコードブロックのコードが実行されるか、途中でwait()に遭遇し、再びロックが解除されるまで、1つ以上の待機中のスレッドが起動し、実行を続行します.
    1.notify/notifyAll()の2つのメソッドの違いnotifyメソッドは、1つの待機(オブジェクトの)スレッドのみを呼び出し、スレッドの実行を開始します.したがって、複数のスレッドが1つのオブジェクトを待つ場合、この方法は1つのスレッドのみを呼び出し、どのスレッドを選択するかは、オペレーティングシステムによるマルチスレッド管理の実装に依存します.notifyAllは、オペレーティングシステムの実装に依存して、どのスレッドが最初に処理されるかにかかわらず、すべての待機(オブジェクトの)スレッドを起動します.現在、複数のスレッドが起動する必要がある場合は、notifyAllメソッドを推奨します.例えば、生産者-消費者の中での使用は、毎回すべての消費者や生産者を呼び覚まし、プログラムが引き続き実行できるかどうかを判断する必要があります.2.notify/notifyAll()を実行するとすぐにロックが解除されますか?いいえnotify/notifyAll()が実行されると、synchronizedコードブロックのコードが実行されるか、途中でwait()に遭遇するまで、対応するオブジェクトの1つ以上の待機中のスレッドが呼び出され、ロックが再び解放されます.すなわち、notify/notifyAll()の実行は、ロックを直ちに解放することなく、眠っているスレッドを呼び覚ますだけであり、ロックの解放はコードブロックの具体的な実行状況に依存する.したがって、プログラミングでは、notify/notifyAll()を使用した直後に臨界領域を終了し、他のスレッドを呼び覚ますようにします.3.wait()とnotify/notifyAll()を使用して生産者と消費者の問題を実現
  • 生産者と消費者の問題は何ですか?まず例を挙げて、あなたは大郎焼餅店に行ってまんじゅうを買って食べて、大郎はまんじゅうがなくなったと言って、あなたは先にしばらく待って、私はこれで金蓮に2つ作ってあげて、あなたは5分待って焼餅が出て、あなたはやっと焼餅を食べました.生産者と消費者モデルの基本原理もこのようにして、生産者は消費者に必要な資源を生み出し、バッファが存在する.消費者はバッファ内の資源を消費し、バッファに必要な資源があることを前提とし、バッファに必要な資源がなければ、消費者は待機状態にあることを停止し、生産者に生産資源を通知する.
  • コードは、名前と年齢を含む既存の学生クラスを実証する.需要:生産者が学生オブジェクトの属性を設定し、消費者が生産者が設定した学生オブジェクトの名前と年齢
  • を印刷する.
  • 試験手順
  • public class MyTest {
        public static void main(String[] args) {
           
            Student student = new Student();
            //     
            SetThread setThread = new SetThread(student);
            //     
            GetThread getThread = new GetThread(student);
            getThread.start();
            setThread.start();
        }
    }
    
  • 学生類
  • public class Student {
        public String name;
        public int age;
        //      
        public boolean flag = false;  //   false       ,true      
    }
    
  • 生産者:
  • public class SetThread extends Thread {
        Student student;
        int i = 0;
    
        public SetThread(Student student) {
            this.student = student;
        }
    
        @Override
        public void run() {
            while (true) {
                synchronized (student) {
                    if (student.flag) {
                        //     ,      
                        try {
                            student.wait(); //  
                        } catch (InterruptedException e) {
                            e.printStackTrace();
                        }
                    }
                    //     
                    if (i % 2 == 0) {
                        student.name = "  ";
                        student.age = 23;
                    } else {
                        student.name = "  ";
                        student.age = 24;
                    }
                    //    
                    student.flag = true;
                    student.notify();//        ,    ,          
                    i++;
                }
    
            }
        }
    }
    
    
  • 消費者
  • public class GetThread extends Thread {
        Student student;
    
        public GetThread(Student student) {
            this.student = student;
        }
    
        @Override
        public void run() {
            while (true) {
                synchronized (student) {
                    if (!student.flag) {
                        //         ,  
                        try {
                            student.wait(); //    ,     ,   ,   ,      
                        } catch (InterruptedException e) {
                            e.printStackTrace();
                        }
                    }
    
                    //    ,   
                    System.out.println(student.name + "===" + student.age);
                    //    
                    student.flag = false;
                    student.notify();
                }
            }
    
        }
    }