Javaマルチスレッド学習(一)
19546 ワード
一、オペレーティングシステムレベルのプロセスとスレッド1.プロセス:
コンピュータプログラムの実行例.実行する命令が含まれており,独自の独立したアドレス空間があり,互いに隔離されている.プロセスには、開いているファイル、サブプロセス、信号処理など、さまざまなリソースとステータス情報があります.2.スレッド:
プログラムの実行フローを表し、CPUが実行をスケジューリングする基本単位である.スレッドには、独自のプログラムカウンタ、同じアドレス空間、プロセスが持つメモリとその他のリソースを共有します.二、Javaにおける同時プログラミングの概要1.同時プログラミングのメリット:
同時プログラミングは、プログラムの実行速度を大幅に向上させるか、いくつかのタイプのプログラムを設計するためにより使いやすいモデルを提供することができます.2.Javaの共通点:
Webアプリケーションは最も一般的なJavaシステムの1つであり、基本的なWebライブラリクラス、サーブレットは生まれつきのマルチスレッド性を持っている.また,グラフィカルユーザインタフェースSwingとSWTクラスライブラリはいずれもスレッドセキュリティに対するメカニズムを有しており,熟練した把握には同時理解が必要である.3.Javaスレッドメカニズムの概要:
Javaスレッドメカニズムはプリエンプト式(非協力式)であり、これはスケジューリングメカニズムが周期的にスレッドを中断し、コンテキストを別のスレッドに切り替えることを意味する.三、Javaにおける単純スレッドプログラミング実装1.javaにおいて最も単純なスレッドプログラミング(1)タスクを実現するタスクを定義するにはRunnableインタフェースを実現しrun()メソッドを記述する必要がある.このタスクが自分の考えを実行できるようにします.
注意:(1)Runnableからクラスをエクスポートするにはrun()メソッドが必要です.(2)Runnableインタフェースの実装は、クラスに内在的なスレッド能力がないタスクを定義するだけである.次の例では、メインメソッドでMainTaskクラスをインスタンス化し、メインスレッド(mainに割り当てられたスレッド)でタスクを呼び出す.
(2)駆動タスクは上記(1)の理解を経て、Javaでタスクを作成する方法について皆さんはすでに理解していると思います.しかし、タスクを定義するだけでは私たちのニーズを満たすことはできません.定義したRunnableオブジェクトを作業タスクに変換することを目的としています.タスクを駆動するには、このRunnableオブジェクトをThreadコンストラクタに提出する必要があります.
Threadクラスの最も基本的な方法:1)Thread.start()メソッド:このメソッドは、スレッド(コンストラクタ内のタスクを実行するスレッド)に必要な初期化操作を実行し、Runnableのrun()メソッドを呼び出して、この新しいスレッドでタスクを開始します. 2)Thread.sleep(int)メソッド:このメソッドのパラメータはミリ秒(ms)単位であり、現在のスレッドで実行されているタスクの指定時間を中止することを意図している.しかし、この書き方はすでに時代遅れであり、現在Java SE(5/6以上)の新しい書き方はTimeUnit.MILLISECONDS.sleep(int)3)Thread.yield()メソッド:このメソッドの呼び出しはスレッドスケジューラに対する推奨です.このメソッドの呼び出しは、プロセスで実行中のタスクがライフサイクルの最も重要な部分を完了したことを宣言することを意味し、タイムスライスを他のタスクに割り当てると、比較的小さな追加コストが発生します.
Threadクラスの方法については後述する.
次の例では、Threadクラスを介してタスクを駆動する方法を示します.
次の例では、複数のスレッドを作成し、複数のタスクを同時に駆動する方法を示します(出力が多すぎるため、サンプル出力は一部省略されます).
2.複数のThreadを管理する前に接触した例は、1つのタスクのみであり、1つのThreadオブジェクトによって駆動される簡単な例です.しかし、私たちの実際のプログラミングでは、Java SE 5のjavaを導入する複数のThreadオブジェクト駆動タスクが必要になることが多い.util.concurrentパッケージのExecutorクラスです.Executorクラスは、Threadオブジェクトを管理し、同時プログラミングを簡単にします.次の例では、Executorを簡単に使用します.
注意:1)例では、静的Executorメソッドを使用して作成されたExecutorServiceオブジェクトを作成します.ここでも、Executorオブジェクトを初期化する際に使用する方法がExecutorsクラスのnewCachedThreadPool()メソッドであることに気づいたかもしれません.ここでは、newFixedThreadPool()メソッドなどの他のメソッドを呼び出してExecutorServiceオブジェクトを初期化することもできます.
両者の違い:CachedThreadPoolは、タスクごとにスレッドを作成します.一方、FixedThreadPoolでは、コストの高いスレッド割当てを一度に実行することができるため、スレッドの数を制限することもできる(CachedThreadPoolに比べて、スレッドの作成ごとのオーバーヘッドを節約できる).2)ExecutorServiceオブジェクトは、静的Executorメソッドを使用して作成され、そのExecutorタイプを決定することができる
四、まとめ
以上の理解から,基本的なタスクおよびスレッドの概念についていくつかの基本的な概念があるはずである.しかし、これは単なる始まりであり、次のブログでは、スレッドに関する知識(スレッドの異常な問題や共有制限されたリソースの解釈に重点を置いている)を引き続き紹介します.
参考書:『Javaプログラミング思想』
コンピュータプログラムの実行例.実行する命令が含まれており,独自の独立したアドレス空間があり,互いに隔離されている.プロセスには、開いているファイル、サブプロセス、信号処理など、さまざまなリソースとステータス情報があります.2.スレッド:
プログラムの実行フローを表し、CPUが実行をスケジューリングする基本単位である.スレッドには、独自のプログラムカウンタ、同じアドレス空間、プロセスが持つメモリとその他のリソースを共有します.二、Javaにおける同時プログラミングの概要1.同時プログラミングのメリット:
同時プログラミングは、プログラムの実行速度を大幅に向上させるか、いくつかのタイプのプログラムを設計するためにより使いやすいモデルを提供することができます.2.Javaの共通点:
Webアプリケーションは最も一般的なJavaシステムの1つであり、基本的なWebライブラリクラス、サーブレットは生まれつきのマルチスレッド性を持っている.また,グラフィカルユーザインタフェースSwingとSWTクラスライブラリはいずれもスレッドセキュリティに対するメカニズムを有しており,熟練した把握には同時理解が必要である.3.Javaスレッドメカニズムの概要:
Javaスレッドメカニズムはプリエンプト式(非協力式)であり、これはスケジューリングメカニズムが周期的にスレッドを中断し、コンテキストを別のスレッドに切り替えることを意味する.三、Javaにおける単純スレッドプログラミング実装1.javaにおいて最も単純なスレッドプログラミング(1)タスクを実現するタスクを定義するにはRunnableインタフェースを実現しrun()メソッドを記述する必要がある.このタスクが自分の考えを実行できるようにします.
1 /**
2 * @author Jayden Ransom
3 * mainTask Runnable ,testMain 。
4 *
5 * */
6 class MainTask implements Runnable {
7 private int numIncrease = 1;
8 private static int taskIncrease = 1;
9 private final int taskId = taskIncrease++;
10 public String toString() {
11 return " " + taskId + " " + numIncrease + " ";
12 }
13 // , run ,
14 public void run() {
15 while(numIncrease <= 10) {
16 System.out.println( toString() );
17 numIncrease++;
18
19 }
20 }
21 }
注意:(1)Runnableからクラスをエクスポートするにはrun()メソッドが必要です.(2)Runnableインタフェースの実装は、クラスに内在的なスレッド能力がないタスクを定義するだけである.次の例では、メインメソッドでMainTaskクラスをインスタンス化し、メインスレッド(mainに割り当てられたスレッド)でタスクを呼び出す.
1 // TestMain , MainTask
2 public class TestMain {
3 public static void main(String args[]) {
4 MainTask mainTask = new MainTask();
5 mainTask.run();
6 }
7 }
8 /*Sample Output:
9 1 1
10 1 2
11 1 3
12 1 4
13 1 5
14 1 6
15 1 7
16 1 8
17 1 9
18 1 10
19 */
(2)駆動タスクは上記(1)の理解を経て、Javaでタスクを作成する方法について皆さんはすでに理解していると思います.しかし、タスクを定義するだけでは私たちのニーズを満たすことはできません.定義したRunnableオブジェクトを作業タスクに変換することを目的としています.タスクを駆動するには、このRunnableオブジェクトをThreadコンストラクタに提出する必要があります.
Threadクラスの最も基本的な方法:1)Thread.start()メソッド:このメソッドは、スレッド(コンストラクタ内のタスクを実行するスレッド)に必要な初期化操作を実行し、Runnableのrun()メソッドを呼び出して、この新しいスレッドでタスクを開始します. 2)Thread.sleep(int)メソッド:このメソッドのパラメータはミリ秒(ms)単位であり、現在のスレッドで実行されているタスクの指定時間を中止することを意図している.しかし、この書き方はすでに時代遅れであり、現在Java SE(5/6以上)の新しい書き方はTimeUnit.MILLISECONDS.sleep(int)3)Thread.yield()メソッド:このメソッドの呼び出しはスレッドスケジューラに対する推奨です.このメソッドの呼び出しは、プロセスで実行中のタスクがライフサイクルの最も重要な部分を完了したことを宣言することを意味し、タイムスライスを他のタスクに割り当てると、比較的小さな追加コストが発生します.
Threadクラスの方法については後述する.
次の例では、Threadクラスを介してタスクを駆動する方法を示します.
1 /**
2 * @author Jayden Ransom
3 * Thread , Thread 。
4 * MainTask ,
5 * */
6
7 public class ThreadTest {
8 public static void main(String args[]) {
9 Thread testThread = new Thread(new MainTask());
10 testThread.start();
11 System.out.println(" ");
12 }
13 }
14 /*Sample Output:
15
16 1 1
17 1 2
18 1 3
19 1 4
20 1 5
21 1 6
22 1 7
23 1 8
24 1 9
25 1 10
26 */
次の例では、複数のスレッドを作成し、複数のタスクを同時に駆動する方法を示します(出力が多すぎるため、サンプル出力は一部省略されます).
1 /**
2 * @author Jayden Ransom
3 * Thread , Thread 。
4 *
5 * */
6
7 public class MoreThreadTest {
8 public static void main(String args[]) {
9 for (int i = 0; i < 5; i++) {
10 new Thread(new MainTask()).start();
11 }
12 }
13 }
14 /*Sample Output:
15 2 1
16 5 1
17 .
18 .
19 .
20 1 2
21 1 3
22 1 4
23 1 5
24 .
25 .
26 5 5
27 .
28 .
29 5 9
30 5 10
31 .
32 .
33 .
34 2 9
35 4 6
36 4 7
37 .
38 .
39 3 9
40 3 10
41 1 10
42 4 10
43 2 10
44
45 */
2.複数のThreadを管理する前に接触した例は、1つのタスクのみであり、1つのThreadオブジェクトによって駆動される簡単な例です.しかし、私たちの実際のプログラミングでは、Java SE 5のjavaを導入する複数のThreadオブジェクト駆動タスクが必要になることが多い.util.concurrentパッケージのExecutorクラスです.Executorクラスは、Threadオブジェクトを管理し、同時プログラミングを簡単にします.次の例では、Executorを簡単に使用します.
1 /**
2 * @author Jayden Ransom
3 * Executor
4 * */
5
6 public class ExecutorTest {
7 public static void main(String args[]) {
8 // Executor
9 ExecutorService exec = Executors.newCachedThreadPool();
10 for (int i = 0; i < 5; i++) {
11 exec.execute(new MainTask() );
12
13 }
14 // shutdown() Executor
15 exec.shutdown();
16 }
17 }
18 /*Sample Output:
19 2 1
20 1 1
21 1 2
22 1 3
23 ...
24 2 10
25 4 7
26 4 8
27 ...
28 3 9
29 4 9
30 4 10
31 3 10
32
33 */
注意:1)例では、静的Executorメソッドを使用して作成されたExecutorServiceオブジェクトを作成します.ここでも、Executorオブジェクトを初期化する際に使用する方法がExecutorsクラスのnewCachedThreadPool()メソッドであることに気づいたかもしれません.ここでは、newFixedThreadPool()メソッドなどの他のメソッドを呼び出してExecutorServiceオブジェクトを初期化することもできます.
両者の違い:CachedThreadPoolは、タスクごとにスレッドを作成します.一方、FixedThreadPoolでは、コストの高いスレッド割当てを一度に実行することができるため、スレッドの数を制限することもできる(CachedThreadPoolに比べて、スレッドの作成ごとのオーバーヘッドを節約できる).2)ExecutorServiceオブジェクトは、静的Executorメソッドを使用して作成され、そのExecutorタイプを決定することができる
四、まとめ
以上の理解から,基本的なタスクおよびスレッドの概念についていくつかの基本的な概念があるはずである.しかし、これは単なる始まりであり、次のブログでは、スレッドに関する知識(スレッドの異常な問題や共有制限されたリソースの解釈に重点を置いている)を引き続き紹介します.
参考書:『Javaプログラミング思想』