目次へ

解答例 - 実習課題2 - 5.スレッドの同期

(実習課題2)

2節のサンプルプログラムを、簡単な待ち行列をシミュレーションするプログラムに改良しなさい。ATMの数を1つ2つと変化させて、シミュレーションを実行しなさい。

  • 待ち行列の長さに上限は無い。つまり待ち行列が一杯なので、待機するという事は無い。
  • 顧客は、平均して3秒に1人到着する。到着間隔は、ポアソン分布に従うのが理想だが、どのようなものでも構わない。
  • ATMは、平均して2秒で1人分のサービスを完了する。サービス時間は、指数分布に従うのが理想だが、どのようなものでも構わない。

解答例

/**
 * QueueTest.java
 * TECHSCORE Java マルチスレッドプログラミング5章 実習課題2 
 *
 * ATMの処理時間、顧客の到着間隔ともに一様分布を利用
 * 
 * Copyright (c) 2004 Four-Dimensional Data, Inc.
 */

package com.techscore.thread.chapter5.exercise2;

import java.util.LinkedList;
import java.util.Iterator;

public class QueueTest {
    public static void main(String[] args) throws Exception {
        Queue queue = new Queue();
        //1台目のATM[A]
        Atm atmA = new Atm(queue, "A");
        //2台目のATM[B]
        Atm atmB = new Atm(queue, "B");
        //お客さんを順番に並ばせる係員
        CustomerManager customerManager = new CustomerManager(queue);

        atmA.start();
        atmB.start();
        customerManager.start();

        long limit = 20000; //閉店までの時間(ミリ秒)
        long start = System.currentTimeMillis(); //開店時間(ミリ秒)
        long now = System.currentTimeMillis(); //現在時間(ミリ秒)
        while (now < start + limit) {
            //閉店時間まで待つ
            now = System.currentTimeMillis();
        }

        //閉店する
        atmA.closeAtm();
        atmB.closeAtm();
        customerManager.closeBank();
        queue.stop();
    }
}

//順番待ちをする場所をあらわすクラス
class Queue {
    LinkedList queue;
    boolean acceptance = true;
    public Queue() {
        queue = new LinkedList();
    }

    //受付を終了するメソッド
    synchronized public void stop() {
        acceptance = false;
        notifyAll();
    }

    //お客さんを順番待ちに追加するメソッド
    synchronized public void put(Customer customer) {
        queue.addFirst(customer);
        printList();
        System.out.println(customer.getNumber() + "番のお客さんが並びました。");
        notifyAll();
    }

    //お客さんを順番待ちから削除してATMへ渡すメソッド
    synchronized public Customer get() {
        while (queue.size() == 0 && acceptance) {
            try {
                wait();
            } catch (InterruptedException e) {
            }
        }
        Customer customer = null;
        if (queue.size() != 0) {
            customer = (Customer)queue.removeLast();
        }
        printList();
        notifyAll();
        //順番待ちをしているお客さんがいればその人を、いなければnullを返す
        return customer;
    }

    //順番待ちのお客さんを表示するメソッド
    synchronized public void printList() {
        System.out.print("順番待ち行列 [ ");
        for (Iterator i = queue.iterator(); i.hasNext();) {
            System.out.print(((Customer)i.next()).getNumber() + " ");
        }
        System.out.println("]");
    }
}

//来店したお客さんを順番に並ばせる係員をあらわすクラス
class CustomerManager extends Thread {
    private Queue queue;
    private boolean open = true;
    public CustomerManager(Queue queue) {
        this.queue = queue;
    }
    public void run() {
        int i = 1; //整理番号

        while (open) {
            //お客さんが来店する
            Customer customer = new Customer();
            //整理番号を渡す
            customer.setNumber(i++);
            //お客さんを順番待ちの最後に並ばせる
            queue.put(customer);
            try {
                Thread.sleep((long) (Math.random() * 6000)); //平均3秒(6秒以下のランダムな時間)
            } catch (InterruptedException e) {
            }
        }
    }
    public void closeBank() {
        open = false;
    }
}

//ATMをあらわすクラス
class Atm extends Thread {
    private String atmName;
    private Queue queue;
    private boolean open = true;
    public Atm(Queue queue, String atm) {
        this.queue = queue;
        this.atmName = atm;
    }

    public void run() {
        while (open) {
            //順番待ちしている先頭のお客さんを呼ぶ
            Customer customer = queue.get();
            //順番待ちのお客さんがいた場合
            if (customer != null) {

                System.out.println(customer.getNumber() + "番のお客さんがATM「" + atmName + "」を利用中です。");
                try {
                    Thread.sleep((long) (Math.random() * 4000)); //平均2秒(4秒以下のランダムな時間)
                } catch (InterruptedException e) {
                }
                System.out.println(customer.getNumber() + "番のお客さんが帰り、ATM「" + atmName + "」が空きました。");
            }
        }
        System.out.println("ATM「" + atmName + "」は閉店しました。");
    }
    public void closeAtm() {
        open = false;
    }

}

//お客さんをあらわすクラス
class Customer {
    private int number; //整理番号

    public int getNumber() {
        return number;
    }
    public void setNumber(int number) {
        this.number = number;
    }
}

↑このページの先頭へ

こちらもチェック!

PR
  • XMLDB.jp