    001/*
    002 * Copyright (c) 2009 The openGion Project.
    003 *
    004 * Licensed under the Apache License, Version 2.0 (the "License");
    005 * you may not use this file except in compliance with the License.
    006 * You may obtain a copy of the License at
    007 *
    008 *     http://www.apache.org/licenses/LICENSE-2.0
    009 *
    010 * Unless required by applicable law or agreed to in writing, software
    011 * distributed under the License is distributed on an "AS IS" BASIS,
    012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
    013 * either express or implied. See the License for the specific language
    014 * governing permissions and limitations under the License.
    015 */
    016package org.opengion.hayabusa.report2;
    017
    018import java.util.concurrent.ConcurrentMap;                                                      // 6.4.3.3 (2016/03/04)
    019import java.util.concurrent.ConcurrentHashMap;                                          // 6.4.3.3 (2016/03/04)
    020
    021/**
    022 * 帳票処理を行う各スレッドを管理するクラスです。
    023 *
    024 * 各スレッドは、内部的にプールされます。
    025 * スレッドのIDはOOoQueue#getThreadId()で返される値です。
    026 * スレッドが生成されるタイミングは、そのIDで初めてスタック要求が来た(insertQueue()が呼ばれた)時です。
    027 *
    028 * 指定のスレッドを終了するには、funishThread( key )を呼び出します。
    029 * 全てのスレッドを終了するには、funishAllThreads()を呼び出します。
    030 *
    031 * 現時点での実装では、生成されたスレッドに対しての監視は行っていません。
    032 * これは、特定のスレッドがフリーズした際、外部から強制終了を行おうとすると、
    033 * 監視スレッドもフリーズしてしまう問題があるためです。
    034 * (但し、1つのsoffice.binのプロセスに対してシリアルに対して処理している限りでは、
    035 *  フリーズ問題は発生しないようです)
    036 *
    037 * @og.group 帳票システム
    038 *
    039 * @version  4.0
    040 * @author   Hiroki.Nakamura
    041 * @since    JDK1.6
    042 */
    043public final class ExecThreadManager {
    044
    045        /** 6.4.3.1 (2016/02/12) 一連の処理で同期を取りたいので、 ConcurrentHashMap は使いません。  */
    046        private static final ConcurrentMap<String, ExecThread> EXEC_POOL = new ConcurrentHashMap<>();           // 6.4.3.3 (2016/03/04)
    047        private static boolean debug    ;               // 4.3.0.0 (2008/07/15) デバッグ追加
    048
    049        /**
    050         * オブジェクトの生成を禁止します
    051         */
    052        private ExecThreadManager() {}
    053
    054        /**
    055         * キューを該当するスレッドにスタックする。
    056         *
    057         * @og.rev 4.3.0.0 (2008/07/15) スレッドIDにシステムIDを付加
    058         *
    059         * @param       queue   ExecQueueオブジェクト
    060         */
    061        public static void insertQueue( final ExecQueue queue ) {
    062                // 4.3.3.6 (2008/11/15) この部分は不要なので元に戻します
    063                final ExecThread oet = getExecThread( queue.getThreadId() );
    064                oet.stackQueue( queue );
    065        }
    066
    067        /**
    068         * キューを該当するスレッドにスタックする
    069         *
    070         * このメソッドでは、既に同じスレッドが存在するかどうかをチェックせずに必ず
    071         * 新しいスレッドを生成し、キューを処理します。
    072         * また、処理が完了した後、そのスレッドは、WAITすることなく終了します。
    073         *
    074         * @og.rev 5.1.6.0 (2010/05/01) 新規作成
    075         *
    076         * @param       queue   ExecQueueオブジェクト
    077         */
    078        public static void insertQueueOnNewThread( final ExecQueue queue ) {
    079                final ExecThread oet = new ExecThread( queue.getThreadId(), debug );
    080                oet.start();
    081                oet.stackQueue( queue );
    082                oet.finishAfterExec();
    083        }
    084
    085        /**
    086         * 該当するスレッドIDを持つスレッドを取得します。
    087         * スレッドプールに存在しない場合は、新規に作成されます。
    088         *
    089         * @og.rev 6.4.3.3 (2016/03/04) Map#compute で対応する。
    090         *
    091         * @param       threadId        スレッドID
    092         *
    093         * @return      ExecThreadスレッド
    094         */
    095        private static ExecThread getExecThread( final String threadId ) {
    096                // Map#compute ： 戻り値は、新しい値。追加有り、置換有り、削除有り
    097                return EXEC_POOL.compute( threadId, (id,oet) ->
    098                                        oet == null || !oet.isAlive() ? ExecThread.startExecThread( id, debug ) : oet );
    099
    100        }
    101
    102        /**
    103         * 全てのスレッドを終了します。
    104         *
    105         * ※ REP21/result2.jsp で、使用。
    106         *
    107         * @og.rev 6.4.3.3 (2016/03/04) Map#forEach で対応する。
    108         */
    109        public static void finishAllThreads() {
    110                EXEC_POOL.forEach( (id,oet) -> oet.finish() );
    111                System.out.println( "[INFO]ALL THREADS FINISHED" );
    112
    113        }
    114
    115        /**
    116         * 指定のスレッドを終了します。
    117         *
    118         * ※ REP21/entry.jsp で、使用。
    119         *
    120         * @param threadId スレッドID
    121         */
    122        public static void finishThread( final String threadId ) {
    123                        final ExecThread oet = EXEC_POOL.remove( threadId );
    124                        // Map上には null はないが、キーが合わない場合は、null が戻る。
    125                        if( oet != null ) {
    126                                oet.finish();
    127                                System.out.println( "[INFO]THREAD CREATED:THREAD-ID=" + threadId );
    128                        }
    129        }
    130
    131        /**
    132         * スレッド情報のマップを返します。
    133         *
    134         * ※ REP21/result2.jsp で、使用。
    135         *
    136         * @og.rev 6.4.3.1 (2016/02/12) PMD refactoring. HashMap → ConcurrentHashMap に置き換え。
    137         * @og.rev 6.4.3.3 (2016/03/04) 戻すMapが、not null制限つきであることを示すため、ConcurrentMap に置き換えます。
    138         * @og.rev 6.4.3.3 (2016/03/04) Map#forEach で対応する。
    139         *
    140         * @return      スレッド情報のマップ
    141         */
    142        public static ConcurrentMap<String, String> getThreadInfo() {
    143                final ConcurrentMap<String, String> infoMap = new ConcurrentHashMap<>();
    144
    145                EXEC_POOL.forEach( (id,oet) -> infoMap.put( id,oet.toString() ) );
    146
    147                return infoMap;
    148        }
    149
    150        /**
    151         * デバッグフラグの設定。
    152         *
    153         * @og.rev 4.3.0.0 (2008/07/15) デバッグ追加
    154         *
    155         * @param   flag デバッグフラグ [true:デバッグ/false:通常]
    156         */
    157        public static void setDebug ( final boolean flag ){
    158                debug = flag;
    159        }
    160}