package org.itscool.commons.threadpool;

/**
 * This class represents the Worker Thread in the Thread Pool.<BR>
 * このクラスは、スレッド・プールで労働者スレッドを代表する。<BR>
 * @author Ashwin Desai.
 * @version 1.10A 2002.06.23 加納 充照 stopFlgの使用を有効化
 */
public final class WorkerThread extends Thread {
    /** ID Generator */
    private static int count;
    /** WorkerThred's ID */
    private int workerId;
    /** Number of Jobs. */
    private int used;
    /** Stop Flag */
    private boolean stopFlag = false;
    /** Request Buffer.(FIFO：先入れ先出し) */
    private FIFOQueue queue;
    /** Debug and Usage stats. */
    private long timeWorked;
    /** Debug and Usage stats.(デバッグと使用統計）*/
    private long timeIdle;
    /** スレッドの待ち状態 */
    private boolean waitStatus;
    /** 待ち状態 */
    public static final boolean WAIT = true;
    /** 待ち状態でない */
    public static final boolean AN_WAIT = false;

    /**
    * 待ち状態のセット
    * 使用側でsynchronizedし使うこと。
    */
    public void setWaitStatus() {
        this.waitStatus = true;
    }

    /**
    * スレッドの待ち状態をアンセット
    * 使用側でsynchronizedし使うこと。
    */
    public void unsetWaitStatus() {
        this.waitStatus = false;
    }

    /**
    * スレッドの待ち状態を取得
    * @return boolean true：待ち状態
    */
    public boolean getWaitStatus() {
        return this.waitStatus;
    }

    /**
     * Creates a WorkerThread object with a shared request queue as parameter.
     * パラメーターとして共有されたリクエスト・キューをもつWorkerThreadオブジ
     * ェクトを作り出します。
     */
    public WorkerThread(FIFOQueue queue) {
        workerId = count++;
        this.queue = queue;
        this.start();
    }

    /**
     * The actual work.(実際の仕事)
     * <pre>
     *  while( thread IS NOT stopped )
     *  {
     *            Get the next request from the queue (this blocks if the queue is empty).
     *            Serve the request.
     *          キューから次のリクエストを受け取って下さい
     *          (もしキューが空っぽなら、これが塞ぎます)。
     *           リクエストを出して下さい。
     *  }
     * </pre>
     */
    public void run() {
        while ( !stopFlag ) {
            //            System.out.println("Thread #" + workerId + "waiting. ....");
            long start = System.currentTimeMillis();
            Runnable r = (Runnable) queue.fetch(this);
            long stop = System.currentTimeMillis();
            timeIdle += (stop - start);
            //            System.out.println("Thread #" + workerId + "working ....");
            r.run();
            //            System.out.println("Thread #" + workerId + "DONE !!");
            timeWorked += (System.currentTimeMillis() - stop);
            // Increment the Usage statistics of this thread
            //(このスレッドの使用統計値をインクリメントする。)
            used++;
        }
    }

    /**
     * Stops the Thread work. i.e. this thread exits it's run() method gracefully.
     * それが優雅にrun ()メソッドであるスレッド仕事。すなわちこのスレッドが終了するストップ。
     */
    public void setStopped() {
        stopFlag = true;
    }

    /**
     * Debug info.
     */
    public String toString() {
        StringBuffer sb = new StringBuffer("Thread # ");
        sb.append(workerId);
        sb.append(" \nUsage :\t");
        sb.append(" Time Idle   : " + timeIdle + " ms");
        sb.append(" Time Worked : " + timeWorked + " ms");
        sb.append(" No of jobs  : " + used);
        return sb.toString();
    }

    /** These methods are for usage stats and debug **/
    /** これらのメソッドは、使い方統計のためにあって、そしてデバッグします **/
    public synchronized long getTimeIdle() {
        return timeIdle;
    }

    public synchronized long getTimeWorked() {
        return timeWorked;
    }

    public synchronized int getJobsDone() {
        return used;
    }

}
