TOP設計・移行・活用> wait()メソッドはwhileブロック内から利用する(C_TRD007)
Javaコーディング規約
Javaコーディング規約

第12回:スレッド・ガベージコレクションに関するコーディング規約
著者: 電通国際情報サービス  高安 厚思、東田 健宏
アイエックス・ナレッジ  河野 弥恵   2006/1/25
前のページ  1  2  3   4  次のページ
wait()メソッドはwhileブロック内から利用する(C_TRD007)

   ある条件が満たされていない時にウェイトとして条件が満たされるのを待つ場合、条件が満たされたことの判定に、if文を使っていないでしょうか。

   ウェイトが終了したら条件が満たされていることを前提とすればif文でもよいのですが、並列処理ではウェイト終了後に別のスレッドが条件を変更している可能性もあります。また、この処理とは関係のないところでnotifyAll()メソッドが発行されているかもしれません。

   If文ではなくwhile文を使用して毎回条件判定を行えば、この危険性を排除できます。

   例えば購入した切符が間違っていたため、待合室で再発行を待つ客の状況を想像してください。if文を使うと、次のようなコーディングになります。

if (購入した切符が間違っている) {
   改札口.wait();   //待合室へ移動
}
//待合室をでたらここから処理を開始

   この場合、待合室には複数の乗降客が切符の再発行を待っています。誰かの切符が再発行されると、呼び出しの放送が掛かります。

   「C_TRD002 ウェイト中のスレッドを再開するときはnotifyAll()メソッドを利用する」の規約に従えば呼び出し放送はnotifyAll()メソッドですので、待合室の全員が外にでてきます。しかし再発行された切符が自分の物ではなかった場合、if文を使ったコーディングでは、もう一度待合室へ戻ることができません。

while(購入した切符が間違っている) {   //待合室をでたら切符を再チェック
   改札口.wait();   //待合室へ移動
}

   このようにwhile文を使用すれば、改札口を通るときにもう一度判定を行うことができます。


ポーリングを利用せずにwait()、notifyAll()メソッドによる待ち合わせを利用する(C_TRD008)

   ある条件が満たされるまでループによって判定を繰り返す方法を、ポーリングループといいます。この方法は、待ち時間が終了するまでループを回し続けるためにCPUリソースを消費してしまい非効率的です。

   条件が満たされていないときはwait()メソッドを実行し、満たされときに実行されるnotifyAll()メソッドを後続処理の開始条件とする方が効率的です。


同期化(synchronized)の適用は必要な部分だけにする(C_TRD009)

   「スレッドの同期化(C_TRD001)」で説明したように、synchronizedを使うとその部分は並列処理ができなくなります。synchronizedブロックで処理を囲む場合は、その範囲をできるだけ限定するようにしてください。

   またメソッドをsynchronized宣言した場合、メソッドだけがロックされる訳ではなく、this(オブジェクトそのもの)にロックが掛かります。

   必要がない場合はメソッドをsynchronized宣言することは避け、synchronizedブロックを使うようにしてください。適用範囲を最小限に抑えることによりスレッドの利用効果を活かし、処理効率を向上させることに繋がります。


ガベージコレクション

   Java言語では、どこからも参照されなくなったオブジェクトは「JavaVM」が自動的に「不要なもの」と判断し、必要な終了処理を行ってメモリを開放します。

   この「回収 → メモリ開放」の動作をガベージコレクションといい、オブジェクトが生成される際の処理が「コンストラクタ」であるのと対照的に、オブジェクトが削除される際に呼び出されるのが「デコンストラクタ」です。Java言語のデコンストラクタは、finalize()メソッドです。

   ガベージコレクションは定期的に呼び出されますが、1回目のガベージコレクション呼び出しで「不要」と判断されたオブジェクトのfinalize()が呼び出され、2回目のガベージコレクション呼び出しですでにfinalize()されているオブジェクトのメモリが開放されます。

   ここでは、finalize()メソッドに関する規約を説明します。


finalize() をオーバーライドした場合はsuper.finalize() を呼び出す(C_GC001)

   finalize()メソッドは、オブジェクトが終了するのに必要なあらゆる処理を記述しておくためのメソッドです。

   サブクラスでfinalize()メソッドをオーバーライドする場合は、必ずsuper.finalize()メソッドを呼び出してください。これは、親クラスのfinalize()メソッドで「オブジェクトが終了するために必要なあらゆる処理」が実装されている可能性があるからです。

   もし、サブクラスでsuper.finalize()メソッドを呼び出さないと、親クラスのfinalize()メソッドで定義されている「オブジェクトが終了するために必要なあらゆる処理」が実行されないことになってしまい、バグの原因になりかねません。


アプリケーションからfinalize()を呼び出さない(C_GC002)

   finalize()メソッドはガベージコレクションが呼び出すためのメソッドです。

   アプリケーションから呼び出すと、その後ガベージコレクションからも呼び出されて2回実行される可能性があります。finalize() の処理にはConnection接続の切断など、2回呼び出されることは想定していない処理が実装されることがあるため、エラーの原因になる可能性があります。

   finalize()とは別に終了処理を記述したい場合は、別の名前でメソッドを作成してください。

前のページ  1  2  3   4  次のページ


株式会社電通国際情報サービス 開発技術センター 高安 厚思
著者プロフィール
株式会社電通国際情報サービス  高安 厚思
株式会社電通国際情報サービス 開発技術センター
Java(J2EE)/オブジェクト指向の研究開発やプロジェクト支援、開発コンサルティングに従事。モデル、アーキテクチャ、プロセスが探求対象。今回は Javaコーディング規約2004の仕掛け人。


株式会社電通国際情報サービス 開発技術センター 東田 健宏
著者プロフィール
株式会社電通国際情報サービス  東田 健宏
株式会社電通国際情報サービス 開発技術センター
CTI、Webアプリの開発経験を経て、現在は主にプロジェクトマネジメント支援、プロセスエンジニアリング、ソフトウェア工学研究開発に従事。最近はコーチング、ファシリテーションといったヒューマン系スキルに興味を持ち日々修得に努めている。


アイエックス・ナレッジ株式会社 河野 弥恵
著者プロフィール
アイエックス・ナレッジ株式会社  河野 弥恵
アイエックス・ナレッジ株式会社 第1事業部所属
主にCOBOL、PL/1等のシステム開発に従事。コーディングに限らず、誰もが気持ちよく守れる規約を模索中。


INDEX
第12回:スレッド・ガベージコレクションに関するコーディング規約
  はじめに
  ウェイト中のスレッドを再開するときはnotifyAll()メソッドを利用する(C_TRD002)
wait()メソッドはwhileブロック内から利用する(C_TRD007)
  その他