排他制御

ファイルはzipフォルダに納められています。
解凍ソフト(Aladdin Expander等)を使って解凍して下さい。

@座席クラスの設計

フィールドの設計

残り座席数を記録する変数を用意します。

private int seat;

コンストラクタ・ゲッタの設計

コンストラクタでは、残り座席数を初期化します。

public Ticket(){
        seat = 5; //初期値は5席
}

残り座席数を返すメソッドを作ります。

public int getSeat(){
        return seat;
}

A発券センターの作成

フィールドの設計

Ticketクラスのオブジェクトと発売開始時刻をチェックするフラグは下記の様にします。

Ticketクラスのオブジェクト
Ticket t = new Ticket();
発売開始を過ぎたかどうかを示すフラグ
Boolean startFlag = false;

コンストラクタ

BorderLayoutで「NORTH」に発券パネルを置き、中央に駅パネルを置きます。

ゲッタメソッド

発売開始時刻を過ぎたかどうかを返すゲッタメソッドを作ります。

public boolean getStartFlag(){
        return startFlag;
}

Ticketクラスのオブジェクトを返すゲッタメソッドを作ります。

public boolean getTicket(){
        return t;
}

発券センターパネルクラス

座席数を示すパネルとスタートボタンを載せます。
スタートボタンは、ボタンクラスを継承した専用の内部クラスを作ります。

スタートボタンクラス

スタートボタンが押されたら、「startFlag」を「true」にします。

/***********ボタンが押されたら************/
public void actionPerformed(ActionEvent e){
        startFlag = true;
}

駅パネルクラス

3×3のグリッドレイアウトにします。

B駅の設計

フィールドの設計

@メインフレームのオブジェクト

Ticket parent;

Aスレッドクラスのオブジェクト

Thread t = null;

B画面に表示する言葉を保存

String message = "準備OK";

C駅番号を保存

int number;

コンストラクタ

@引数として受け取ったTicketRaceクラスのオブジェクトを保存
A背景を灰色に
Bスレッドスタート

paintComponent(表示)

@駅の画像とメッセージを表示
A駅の画像は、駅番号により選択

TicketRaceクラスで駅パネルに駅を載せる

駅パネルのコンストラクタで、駅を9つインスタンス化して、GridLayoutの枠に1つずつ載せます。

Cスレッドの実行をトレース

MS-DOSの画面にスレッドの実行の様子を表示

現象を確かめる為には、TicketThread.javaの54行目のtakeSeatメソッドの呼び出し時にスレッド名を渡し、takeSeatメソッドでは、以下の様にMS-DOSに出力する命令を加えて、実行の様子をトレースしてみましょう。

スレッドの実行を制御

MS-DOS画面に表示された様にBのプログラムは、9つのスレッドが発売開始を知って、一斉に動いた為に、残席有りになって終う様な事が起きたのです。
つまり問題なのは、「席が確保出来るかどうかのチェックをした後で、しかし実際には、未だ確保していない(seatを1減らしていない時に、別のスレッドが処理を開始して終う事」です。
此を解決するには、有るスレッドがtakeSeatメソッドを実行中には、他のスレッドは、此のスレッドの実行を待っている状態にする必要が有ります。

D排他制御

有るスレッドが処理を実行している間は、他のスレッドが途中で割り込めない様にする事を排他制御と言います。
Javaでは、メソッドを実行中、割り込み禁止にしたいメソッドの宣言に、「synchronized」と言うキーワードを付けます。

ソース ダウンロード
Ticket.java Ticket.zip
TicketThread.java
TicketRace.java

戻る