プログラムと例を使用した Java チュートリアルのマルチスレッド化
どのアプリケーションも複数のプロセス (インスタンス) を持つことができます。この各プロセスは、単一のスレッドまたは複数のスレッドとして割り当てることができます。このチュートリアルでは、同時に複数のタスクを実行する方法を確認し、スレッドとスレッド間の同期についても学習します。
この Java のマルチスレッド チュートリアルでは、次のことを学びます。
- シングルスレッドとは
- Java のマルチスレッドとは
- Java のスレッド ライフ サイクル
- Java スレッドの同期
- Java マルチスレッドの例
シングル スレッドとは
Java の単一スレッドは、基本的に軽量で最小の処理単位です。 Java は「スレッド クラス」を使用してスレッドを使用します。
スレッドには、 ユーザー スレッドとデーモン スレッド の 2 種類があります。 (デーモン スレッドは、アプリケーションをクリーンアップするときに使用され、バックグラウンドで使用されます)。
アプリケーションが最初に開始されると、ユーザー スレッドが作成されます。それを投稿すると、多くのユーザー スレッドとデーモン スレッドを作成できます。
シングル スレッドの例:
package demotest; public class GuruThread { public static void main(String[] args) { System.out.println("Single Thread"); } }
シングル スレッドの利点:
- システムでシングル スレッドが実行されるため、アプリケーションのオーバーヘッドが削減されます
- また、アプリケーションのメンテナンス コストを削減します。
Java のマルチスレッドとは
マルチスレッド Java では、2 つ以上のスレッドを同時に実行して CPU の使用率を最大にするプロセスです。マルチスレッド アプリケーションは、同時に実行される 2 つ以上のスレッドを実行します。そのため、Java では並行性とも呼ばれます。各スレッドは互いに並行して実行されます。複数のスレッドは個別のメモリ領域を割り当てないため、メモリを節約できます。また、スレッド間のコンテキスト切り替えにかかる時間も短縮されます。
マルチスレッドの例:
package demotest; public class GuruThread1 implements Runnable { public static void main(String[] args) { Thread guruThread1 = new Thread("Guru1"); Thread guruThread2 = new Thread("Guru2"); guruThread1.start(); guruThread2.start(); System.out.println("Thread names are following:"); System.out.println(guruThread1.getName()); System.out.println(guruThread2.getName()); } @Override public void run() { } }
マルチスレッドの利点:
- スレッドは独立しているため、ユーザーはブロックされず、複数の操作を同時に実行できます
- スレッドは独立しているため、1 つのスレッドが例外に遭遇しても、他のスレッドは影響を受けません。
Java でのスレッドのライフ サイクル
スレッドのライフサイクル:
<センター>
<図>Java でのスレッドのライフサイクル
フィギュア>センター>
上の図に示すように、スレッドのライフサイクルにはさまざまな段階があります:
<オール>
スレッドで一般的に使用されるメソッドには次のものがあります:
方法 | 説明 |
---|---|
start() | このメソッドはスレッドの実行を開始し、JVM はスレッドで run() メソッドを呼び出します。 |
スリープ (int ミリ秒) | このメソッドはスレッドをスリープ状態にするため、スレッドの実行は指定されたミリ秒間一時停止し、その後、スレッドは再び実行を開始します。これは、スレッドの同期に役立ちます。 |
getName() | スレッドの名前を返します。 |
setPriority(int newpriority) | スレッドの優先度を変更します。 |
利回り () | 現在のスレッドを停止させ、他のスレッドを実行させます。 |
例: この Java のマルチスレッド プログラムの例では、スレッドを作成し、スレッドで使用できる組み込みメソッドを調べます。
package demotest; public class thread_example1 implements Runnable { @Override public void run() { } public static void main(String[] args) { Thread guruthread1 = new Thread(); guruthread1.start(); try { guruthread1.sleep(1000); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } guruthread1.setPriority(1); int gurupriority = guruthread1.getPriority(); System.out.println(gurupriority); System.out.println("Thread Running"); } }
コードの説明:
- コード行 2: Runnable インターフェースを実装するクラス「thread_Example1」を作成しています (インスタンスがスレッドによって実行されることを意図しているクラスによって実装する必要があります)。
- コード行 4: メソッドをオーバーライドすることが必須であるため、実行可能なインターフェースの実行メソッドをオーバーライドします
- コード 6 行目: ここで、スレッドの実行を開始するメイン メソッドを定義しました。
- コード行 7: ここでは、スレッドの新しいクラスをインスタンス化して、「guruthread1」という新しいスレッド名を作成しています。
- コード行 8: 「guruthread1」インスタンスを使用してスレッドの「start」メソッドを使用します。ここでスレッドの実行が開始されます。
- コード 10 行目: ここでは、「guruthread1」インスタンスを使用するスレッドの「スリープ」メソッドを使用しています。したがって、スレッドは 1000 ミリ秒間スリープします。
- コード 9-14: ここでは、発生するチェック例外、つまり割り込み例外があるため、sleep メソッドを try catch ブロックに配置しています。
- コード 15 行目: ここでは、スレッドの優先度を 1 に設定しています。
- コード 16 行目: ここでは、getPriority() を使用してスレッドの優先度を取得しています
- コード 17 行目: ここでは、getPriority から取得した値を出力しています
- コード 18 行目: ここでは、スレッドが実行されているテキストを書いています。
上記のコードを実行すると、次の出力が得られます:
出力:
5 はスレッドの優先度であり、実行中のスレッドはコードの出力であるテキストです。
Java スレッドの同期
マルチスレッドでは、プログラムの非同期動作があります。あるスレッドがデータを書き込み、別のスレッドが同時にデータを読み取っている場合、アプリケーションに矛盾が生じる可能性があります。
2 つ以上のスレッドが共有リソースにアクセスする必要がある場合は、同期アプローチが利用されます。
Java は同期動作を実装する同期メソッドを提供しています。
このアプローチでは、スレッドが同期ブロック内に到達すると、他のスレッドは同じオブジェクトでそのメソッドを呼び出すことができなくなります。すべてのスレッドは、そのスレッドが同期ブロックを終了してそこから出るまで待機する必要があります。
このように、同期はマルチスレッド アプリケーションに役立ちます。 1 つのスレッドは、他のスレッドが実行を終了するまで待機する必要があり、その後で他のスレッドの実行が許可されます。
次の形式で記述できます:
Synchronized(object) { //Block of statements to be synchronized }
Java マルチスレッドの例
このマルチスレッド Java の例では、2 つのスレッドを取り、スレッドの名前をフェッチします。
例 1:
GuruThread1.java package demotest; public class GuruThread1 implements Runnable{ /** * @param args */ public static void main(String[] args) { Thread guruThread1 = new Thread("Guru1"); Thread guruThread2 = new Thread("Guru2"); guruThread1.start(); guruThread2.start(); System.out.println("Thread names are following:"); System.out.println(guruThread1.getName()); System.out.println(guruThread2.getName()); } @Override public void run() { } }
コードの説明:
- コード行 3: Runnable を実装するクラス「GuruThread1」を使用しました (インスタンスがスレッドによって実行されることを意図している任意のクラスによって実装する必要があります)。
- コード行 8: これはクラスのメイン メソッドです
- コード行 9: ここでは、Thread クラスをインスタンス化し、「guruThread1」という名前のインスタンスを作成して、スレッドを作成しています。
- コード 10 行目: ここでは、Thread クラスをインスタンス化し、「guruThread2」という名前のインスタンスを作成して、スレッドを作成しています。
- コード 11 行目: スレッド、つまり guruThread1 を開始しています。
- コード 12 行目: スレッド、つまり guruThread2 を開始しています。
- コード 13 行目: テキストを「スレッド名は次のとおりです:」として出力する
- コード 14 行目: スレッド クラスのメソッド getName() を使用して、スレッド 1 の名前を取得します。
- コード 15 行目: スレッド クラスのメソッド getName() を使用して、スレッド 2 の名前を取得します。
上記のコードを実行すると、次の出力が得られます:
出力:
スレッド名はここに出力されています
- 達人1
- 達人2
例 2:
この Java のマルチスレッド化の例では、実行可能なインターフェースのメソッド run() および start() メソッドをオーバーライドする方法を学び、そのクラスの 2 つのスレッドを作成し、それに応じてそれらを実行します。
また、私たちは 2 つのクラスを受講しています。
- 実行可能なインターフェースを実装するもの
- メイン メソッドを持ち、それに応じて実行される別のメソッド
package demotest; public class GuruThread2 { public static void main(String[] args) { // TODO Auto-generated method stub GuruThread3 threadguru1 = new GuruThread3("guru1"); threadguru1.start(); GuruThread3 threadguru2 = new GuruThread3("guru2"); threadguru2.start(); } } class GuruThread3 implements Runnable { Thread guruthread; private String guruname; GuruThread3(String name) { guruname = name; } @Override public void run() { System.out.println("Thread running" + guruname); for (int i = 0; i < 4; i++) { System.out.println(i); System.out.println(guruname); try { Thread.sleep(1000); } catch (InterruptedException e) { System.out.println("Thread has been interrupted"); } } } public void start() { System.out.println("Thread started"); if (guruthread == null) { guruthread = new Thread(this, guruname); guruthread.start(); } } }
コードの説明:
- コード行 2: ここでは、main メソッドを含むクラス「GuruThread2」を使用しています。
- コード行 4: ここでは、クラスのメイン メソッドを使用しています。
- コード行 6 ~ 7: ここでは、クラス GuruThread3 (コードの下の行で作成) のインスタンスを「threadguru1」として作成し、スレッドを開始しています。
- コード行 8 ~ 9: ここでは、クラス GuruThread3 の別のインスタンス (以下のコード行で作成) を「threadguru2」として作成し、スレッドを開始しています。
- コード 11 行目: ここでは、実行可能なインターフェイスを実装するクラス「GuruThread3」を作成しています (インスタンスがスレッドによって実行されることを意図しているクラスによって実装する必要があります)。
- コード行 13 ~ 14: 2 つのクラス変数を取得しています。1 つはスレッド クラス型で、もう 1 つは文字列クラスです。
- コード行 15 ~ 18: クラス変数 guruname に割り当てられる文字列型 (スレッド名) として 1 つの引数を取る GuruThread3 コンストラクターをオーバーライドしているため、スレッドの名前が格納されます。
- コード行 20: ここでは、実行可能なインターフェースの run() メソッドをオーバーライドしています。
- コード行 21: println文でスレッド名を出力しています。
- コード行 22 ~ 31: ここでは、カウンターが 0 に初期化された for ループを使用しています。これは 4 未満であってはならず (任意の数を使用できるため、ここではループが 4 回実行されます)、カウンターをインクリメントします。スレッド名を出力し、スリープ メソッドがチェック例外を発生させたため、try-catch ブロック内でスレッドを 1000 ミリ秒間スリープさせます。
- コード 33 行目: ここでは、実行可能なインターフェースの start メソッドをオーバーライドしています。
- コード 35 行目: 「スレッド開始」というテキストを出力しています。
- コード行 36 ~ 40: ここでは、if 条件を使用して、クラス変数 guruthread に値が含まれているかどうかを確認しています。 null の場合は、名前をパラメーター (コンストラクターで割り当てられた値) として受け取るスレッド クラスを使用してインスタンスを作成しています。その後、start() メソッドを使用してスレッドが開始されます。
上記のコードを実行すると、次の出力が得られます:
出力 :
スレッドが 2 つあるため、「スレッドが開始されました」というメッセージが 2 回表示されます。
出力したスレッドの名前を取得します。
カウンターとスレッド名を出力する for ループに入り、カウンターは 0 から始まります。
ループは 3 回実行され、その間にスレッドは 1000 ミリ秒間スリープします。
したがって、最初に guru1、次に guru2、そして再び guru2 を取得します。これは、スレッドがここで 1000 ミリ秒スリープし、次の guru1 と再び guru1、スレッドが 1000 ミリ秒スリープするため、guru2、次に guru1 を取得するためです。
まとめ
このチュートリアルでは、Java のマルチスレッド アプリケーションと、Java でシングル スレッドとマルチ スレッドを使用する方法について説明しました。
- Java でのマルチスレッドについて説明します。マルチスレッドでは、スレッドが独立していて、一度に複数の操作を実行できるため、ユーザーはブロックされません
- スレッドのライフサイクルのさまざまな段階は、
- 新規
- 実行可能
- ランニング
- 待っています
- 死んだ
- アプリケーションのスムーズな実行に役立つスレッド間の同期についても学びました。
- Java でのマルチスレッド プログラミングにより、より多くのアプリケーション タスクが容易になります。
Java