上記以外にスレッドを制御するためのJava文法として「synchronized」というキーワードがあります。これは、複数のスレッドから同時にアクセスされることを防ぐための機構で、2通りの使い方があります。
1つは上記のようにメソッドに付けて使用します。こうしたメソッドを「synchronizedメソッド」と呼びます。
synchronized void foo() { for (int i = 0; i < 10; i++) { System.out.println(i); } }
synchronizedが付いたメソッドは、そのメソッドが複数のスレッドから呼び出されたとしても、必ず現在実行中のスレッドでメソッドが終了してから次が呼び出されます。
もう1つは、以下のように使用します。
int[] array = new int[10]; void foo() { synchronized (array) { for (int i = 0; i < array.length; i++) { System.out.println(array[i]); } } } void bar() { synchronized (array) { for (int i = 0; i < array.length; i++) { array[i] += i; } } }
synchronizedの後ろで指定されているのは「相互排他ロック」といいます。上記例ではarrayという配列で相互排他を行っており、複数スレッドからfoo()メソッドとbar()メソッドにアクセスした場合、以下のような動作になります。
Trimisでは、ユーザースレッド(自分で作成したスレッド)が1つしかなく、システムスレッドと同期をしなくてもよいように設計しているためsynchronizedは使用していませんが、これからもっともっとJavaプログラムを作っていくなら、いつかきっと必要になるときがきますので、動作の概念をよく理解して、迷ったら読み返してみてください。
さて、追加したコードに説明を戻します。run()メソッドがスレッドの処理の本体で、今回の実装でコードがたくさん追加されています。メソッドの最初に定義されているxとyは、ブロックの座標を表しています。yの値が大きいほどブロックは落下していることを表します。
同じく最初に定義されているcountは、モードが落下中であれば1つずつ増えていく変数です。これが20で割り切れる値になったら、y座標を1つ増やしています。
if (count != 0) { if (count % 20 == 0) { y++; } }
落下中は約50ミリ秒に1回の間隔でcountが1つずつ増えていくので、ブロックが自然に落ちていくのは1秒に1行ですね。このように、スリープ(一時的に停止)をしながら処理を繰り返すスレッドを、特に「メインループ」といいます。
先ほどのJavaファイルをダウンロードして、再びソースコードを差し替えて実行してみてください。
自動落下を実装したソースコードをコンパイルして、実行させてみたでしょうか。実行させたら落下しているブロックが一番下まで到達するのをじっと待ってみてください。コンソール部分の最後に、iDK(DOJO)とWTK(MIDP)でそれぞれ以下のメッセージが表示されます。
「Uncaught exception java/lang/ArrayIndexOutOfBoundsException.」というメッセージは、日本語にすると「キャッチされなかった例外 java/lang/ArrayIndexOutOfBoundsException.」となります。
今回はスレッドの仕組みを理解し、例外が発生するところまでを確認しました。例外は基本的には発生してはいけない「エラーのようなもの」なのですが、「発生させないようにするにはどうしなければならないのか」「発生した場合はどのようにするべきか」「発生する可能性がある場合はどうしたらよいか」などを学びつつ、途中になっている実装を次回は進めていきましょう。
Copyright © ITmedia, Inc. All Rights Reserved.