Java で wait() メソッドと Notice() メソッドを使用して共有リソースのインスタンスを操作する方法
この記事では、Java が共有リソースを操作するために wait() Notice() メソッドを使用する方法を主に詳しく紹介します。興味のある方は参照してください。
Java の複数のスレッドはリソースを共有します。 )、notify()、notifyAll() メソッドはローカル メソッドであり最終メソッドであり、オーバーライドできません。
2) オブジェクトの wait() メソッドを呼び出すと、現在のスレッドがブロックされる可能性があり、現在のスレッドはこのオブジェクトのモニター (つまり、ロック、またはモニター) を所有する必要があります
3) オブジェクトの Notice() メソッドを呼び出すこのオブジェクトのモニターを待機しているスレッドをウェイクアップできます。このオブジェクトのモニターを待機しているスレッドが複数ある場合、そのうちの 1 つだけをウェイクアップできます。4) NoticeAll() メソッドを呼び出すと、すべてのスレッドをウェイクアップできます。このオブジェクトを待機しているスレッド。 監視スレッド
Java には、PV 操作、プロセス相互排他などに関連するメソッドはありません。 JAVA のプロセス同期は、synchronized() を通じて実現されます。Java の synchronized() メソッドは、Java のオブジェクト クラス オブジェクトの後にある相互排他的なメモリ ブロックに似ていることに注意してください。スレッドがメモリ ロックを取得すると、他のスレッドはメモリにアクセスできなくなり、Java での単純な同期と相互排他操作が実現されます。この原則を理解すると、synchronized(this) と synchronized(static XXX) の違いが理解できるようになります。 synchronized はメモリ ブロックのメモリ ロックに適用されるため、そのメモリ ロックはクラスのオブジェクトを表します。同じオブジェクト 相互に排他的な操作。静的メンバーはクラスに対して排他的であり、そのメモリ空間はクラスのすべてのメンバーによって共有されます。これにより、synchronized() は静的メンバーをロックします。これはクラスをロックすることと同じです。 、クラスのすべてのメンバー間で相互排他を実装するには、このクラスのインスタンスに同時にアクセスできるスレッドは 1 つだけです。スレッド間で相互にウェイクアップする必要がある場合は、Object クラスの wait() メソッドと nofity() メソッドを使用する必要があります。
こんなに話しても理解できないかもしれないので、マルチスレッドを使用して連続 1,2,1,2,1,2,1,2,1,2 出力を実現する例を使用して問題を説明しましょう。 。
package com.study.thread; /** * 多线程 * @ClassName: PrintFile * @date 2017年10月10日 下午4:05:04 */ public class PrintFile implements Runnable{ //当前线程id private int id ; //共享资源 public byte[] res ; //如果类里写了有参构造器,而任然想保留无参数构造方法,则必须显式的写出该方法。 public PrintFile() { super(); // System.out.println("我是构造器"); } public PrintFile(int id, byte[] res) { //构造器中使用super()/this(),必须放在第一行。 this(); this.id = id; this.res = res; } //静态计数器 public static int count = 5; @Override public void run() { synchronized (res) { while(count-->=0){ try { res.notify();//唤醒其他线程中的某一个(唤醒等待res的其他线程,当前线程执行完后要释放锁) System.out.println("当前线程id值:"+id); res.wait();//当前线程阻塞,等待被唤醒 System.out.println("现在执行的线程是"+Thread.currentThread().getName()+",--wait()后的代码继续执行:"+id); } catch (InterruptedException e) { e.printStackTrace(); } } return; } } }
package com.study.thread; public class PrintFileTest { public static void main(String[] args) { byte[] res = new byte[]{0,1,2};//共享资源 PrintFile p1 = new PrintFile(1, res); PrintFile p2 = new PrintFile(2, res); Thread t1 = new Thread(p1, "a"); Thread t2 = new Thread(p2, "b"); t1.start(); t2.start(); } }
現在のスレッドID値: 1
現在実行されているスレッドはaであり、--wait()の後のコードは継続します。実行: 1
現在のスレッド ID 値: 1現在実行中のスレッドは b、--wait() の後のコードは実行を継続します: 2
現在のスレッド ID 値: 2
現在実行中のスレッドは a、- の後のコード-wait() コードは実行を継続します: 1
現在のスレッド ID 値: 1
現在実行中のスレッドは b, --wait() --wait() の後のコードは実行を継続します: 2
現在のスレッド ID 値: 2
現在実行中のスレッドは a, --wait () 以降のコードは実行を継続します: 1
このような結果が発生する理由を以下に説明します:
まず、スレッド 1 と 2 が開始されると仮定します。最初に run メソッドを実行してリソースを取得します (実際には不確実です)。 オブジェクト a のロックを取得し、while ループに入ります (複数回の出力を制御するために使用されます): この時点で、オブジェクトは wake-1 を呼び出します。これは、同期ブロックが実行された後、ロックを解放し、リソースを待機しているスレッドに渡します。 出力 1;
3。これは、この時点からオブジェクト ロックを所有するスレッド (つまり、ここではスレッド No. 1) が CPU 制御を解放することを意味し、ロックが解放され、スレッドはブロッキング状態になります。同期ブロックは実行されていないため、1 は効果がありません。
4. これより前の時点で、スレッド 2 は run メソッドを実行しましたが、オブジェクト a のロックを取得できなかったため、実行を続けることができません。しかし、3ステップ後にaのロックを取得します。このとき、aのウェイクアップメソッドnotify()を実行します。これは、同期ブロックの実行後にロックを解放することを意味します。 put リソース a を待機しているスレッドにロックが渡されます
5. 出力 2、つまり、この時点からオブジェクト ロックを所有するスレッド (スレッド) を実行します。ここでは No.2) CPU 制御を解放します。 ロックが解放され、スレッドはブロッキング状態になります。同期ブロックが実行されていないため、スレッドの 4 段階のウェイクアップ方法は一時的に実行されません。 2 番は機能しません。
7. この時点で、スレッド 1 が実行されます。 ステップ 3 では、オブジェクト ロックが使用されていないことがわかり、ステップ 3 の wait メソッド以降のコードが実行され続けます。したがって、出力は次のようになります: ------スレッド 1 がロックを取得し、wait() の後のコードは実行を継続します: 1;
8. この時点で、while ループは条件を満たし、実行を継続します。 、スレッド No. 1 のウェイクアップ メソッドを実行します。これは、同期ブロックの実行後にロックを解放します。
10. 待機中のメソッド 1 を実行し、リソース ロック;
11. この時点で、スレッド 2 は再度ロックを取得し、ステップ 6 を実行し、wait メソッドの後にコードを実行し続けるため、出力は次のようになります。 ------ スレッド 2 がロックを取得します。 wait () の後のコードは実行を続けます: 2;
12. while ループを実行し続けて 2; を実行します。 2つの方法がありますが、これもプログラムに問題があり、whileループが条件を満たさない場合、リソースを待っているスレッドが確実に存在するため、メインスレッドは終了しません。もちろん、このプログラムの目的は、これら 2 つの方法の使用方法を示すことだけです。
概要:wait() メソッドと notify() は synchronized(resource) と一緒に使用する必要があります。つまり、wait と notification は、リソース ロックを取得したスレッド上で動作します。構文の観点からは、Obj.wait() と Obj.notify は synchronized(Obj){...} ステートメント ブロック内にある必要があります。機能的に言えば、オブジェクト ロックを取得した後、wait() スレッドは CPU 制御とオブジェクト ロックを積極的に解放し、同時にこのスレッドはスリープします。別のスレッドがオブジェクトのnotify()を呼び出してスレッドをウェイクアップするまで、オブジェクトのロックを取得し続けて実行を続けることができます。対応するnotify()は、オブジェクトのロックの解放操作です。 [したがって、wait メソッドとnotify メソッドの両方がオブジェクトのロックを解放できることがわかりますが、wait メソッドは CPU 制御も解放します。つまり、その背後にあるコードは実行を停止し、スレッドはブロック状態になりますが、notify メソッドは解放しません。 CPU は直ちに制御しますが、対応する synchronized(){} ステートメント ブロックの実行が終了すると、ロックは自動的に解放されます。 】ロックを解放した後、JVM はリソースを待っているスレッドの中からスレッドを選択し、それにオブジェクト ロックを付与し、スレッドをウェイクアップして実行を継続します。これにより、スレッド間の同期とウェイクアップ操作が提供されます。 Thread.sleep() と Object.wait() は両方とも、現在のスレッドを一時停止して CPU 制御を解放できます。主な違いは、Object.wait() は同期ブロック内で CPU を解放しながらオブジェクトのロック制御を解放することです。 sleep() メソッドはロックを解放せず、CPU 制御のみを解放します。
以上がJava で wait() メソッドと Notice() メソッドを使用して共有リソースのインスタンスを操作する方法の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

ホットAIツール

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

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

Undress AI Tool
脱衣画像を無料で

Clothoff.io
AI衣類リムーバー

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

人気の記事

ホットツール

メモ帳++7.3.1
使いやすく無料のコードエディター

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

ゼンドスタジオ 13.0.1
強力な PHP 統合開発環境

ドリームウィーバー CS6
ビジュアル Web 開発ツール

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

ホットトピック









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

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

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

Java での日付までのタイムスタンプに関するガイド。ここでは、Java でタイムスタンプを日付に変換する方法とその概要について、例とともに説明します。

カプセルは3次元の幾何学的図形で、両端にシリンダーと半球で構成されています。カプセルの体積は、シリンダーの体積と両端に半球の体積を追加することで計算できます。このチュートリアルでは、さまざまな方法を使用して、Javaの特定のカプセルの体積を計算する方法について説明します。 カプセルボリュームフォーミュラ カプセルボリュームの式は次のとおりです。 カプセル体積=円筒形の体積2つの半球体積 で、 R:半球の半径。 H:シリンダーの高さ(半球を除く)。 例1 入力 RADIUS = 5ユニット 高さ= 10単位 出力 ボリューム= 1570.8立方ユニット 説明する 式を使用してボリュームを計算します。 ボリューム=π×R2×H(4

Spring Bootは、Java開発に革命をもたらす堅牢でスケーラブルな、生産対応のJavaアプリケーションの作成を簡素化します。 スプリングエコシステムに固有の「構成に関する慣習」アプローチは、手動のセットアップを最小化します。
