【プログラミング中級者向け】さあ、マルチスレッドプログラミングをはじめよう その2
ではマルチスレッドを書く具体的な方法をお伝えします!
それは、、、
【Executor framework】です!!
Executor frameworkとは、、
スレッドプールをベースとしたシンプルな並列処理APIです。
処理を「Task」と言われる粒度に分解して考え、スレッドプールに割り当てて実行します。
TaskはRunnableインタフェースを継承したクラスまたはラムダ式で表現するため、実質的には「スレッドプールをサポートしたThreadの上位互換」として利用することが出来るでしょう。
また通常はFutureを取り扱えるExecutorServiceというExecutorを使います。
ややこしい!
簡単にまとめると、ExcutorServiceを使ってマルチスレッドの処理を書けるということです。
実際の処理がこちら。
public static void main(String[] args) throws Exception {
ExecutorService es = Executors.newFixedThreadPool(2); //1
try {
es.execute(() -> System.out.println("executor:1, thread-id:" + Thread.currentThread().getId())); //2
es.execute(() -> System.out.println("executor:2, thread-id:" + Thread.currentThread().getId()));
es.execute(() -> System.out.println("executor:3, thread-id:" + Thread.currentThread().getId()));
es.execute(() -> System.out.println("executor:4, thread-id:" + Thread.currentThread().getId()));
es.execute(() -> System.out.println("executor:5, thread-id:" + Thread.currentThread().getId()));
} finally {
try {
es.shutdown(); //3
if (!es.awaitTermination(1, TimeUnit.MINUTES)) { //4
es.shutdownNow(); //5
}
} catch (InterruptedException e) {
System.out.println("awaitTermination interrupted: " + e);
es.shutdownNow();
}
}
}
実際の結果がこちら。
executor:1, thread-id:11
executor:2, thread-id:11
executor:3, thread-id:12
executor:4, thread-id:12
executor:5, thread-id:12
スレッドが11と12の2つで行われているため、マルチで実行されていますね!
では解説していきます!
1.マルチスレッドの処理を行えるサービスクラスExecutorServiceを宣言・初期化しています。このときExecutorsクラスのnewFixedThreadPool()メソッドを使い、指定数のスレッドを再利用するスレッドプールを設定しています。今回は11と12のidの2つのスレッドをプールしています。
2.ExecutorServiceクラスのexecuteメソッドで出力処理を実行しています。
ラムダ式で記述されており、匿名クラスが変換されています。
es.execute(new Runnable() {
@Override
public void run() {
System.out.println("executor:1, thread-id:" + Thread.currentThread().getId());
}
});
Eclipseならクイックフィックス(Cmd+1)でも確認できます!
3.ExcutorServiceクラスのshutdownメソッドを使って、シャットダウンを開始します。
shutdownメソッドは指示するだけ。
学校で先生が生徒に対して、「問題が解けたら教えてねー」と言います。
でも先生(shutdownメソッド)は何もしません。「先生できたー!!」って言ってくるまで「かたくな」に待ちますw
shutdownメソッドは指示するだけだからです。
4.そこでawaitTerminationメソッドです。
ある一定時間待ってもタスクが終わらない場合、
タスクを中断させることで、ずっとタスク完了を待つことをしないですみます。
使い方としては、shutdownメソッド実行後にawaitTerminationを実行します。
awaitTerminationの第一引数の時間だけ同期して待ちます。
指定した時間内に全てのタスクが完了した場合、trueを返します。
指定した時間経っても全てのタスクが完了しない場合、falseを返します。
falseを返されるというのは、授業の時間が終わっても、
問題が解けていない生徒がいる状態です。
5.なので「解けてない人宿題で明日提出しなさい!!」と言って授業を終わらせましょう!
shutdownNowメソッドがやってくれます。
shutdownNowメソッドは、実行中の全てのスレッドに対してinterruptedを発行してスレッドを中断します。
まとめると、
・ExecutorServiceサービスでマルチスレッド処理を書くことができる
・実行順序はshutdownメソッド、awaitTerminationメソッド、shutdownNowメソッド(例外発生時、タイムアウト時のみ)
ではまた次回の投稿をお楽しみに〜!
参考文献
https://qiita.com/koduki/items/086d42b5a3c74ed8b59e
http://mobiles-han.blogspot.com/2012/12/executorserviceshutdown.html
https://qiita.com/bremen/items/b87bff49565fc9abc91b
この記事が気に入ったらサポートをしてみませんか?