    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.HashMap;
    019import java.util.Map;
    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        /**
    046         * スレッドプール
    047         */
    048        private static final Map<String, ExecThread>      pool    = new HashMap<String, ExecThread>();
    049        private static boolean debug    = false; // 4.3.0.0 (2008/07/15) デバッグ追加
    050
    051//      /**
    052//       * チェックスレッドの実行間隔
    053//       */
    054//      private static final int REPORT_THREAD_CHECK_INTERVAL = 1000 * 2;
    055
    056//      /**
    057//       * OOoがクラッシュしていると判断される停止時間
    058//       */
    059//      private static final int REPORT_THREAD_CRASH_TIME = 1000 * 2;
    060
    061//      /**
    062//       * チェック用のスレッドを開始します
    063//       */
    064//      static {
    065//              checkThreads();
    066//      }
    067
    068        /**
    069         * オブジェクトの生成を禁止します
    070         */
    071        private ExecThreadManager() {}
    072
    073        /**
    074         * キューを該当するスレッドにスタックする
    075         *
    076         * @og.rev 4.3.0.0 (2008/07/15) スレッドIDにシステムIDを付加
    077         *
    078         * @param       queue   ExecQueueオブジェクト
    079         */
    080        public static void insertQueue( final ExecQueue queue ) {
    081                // 4.3.3.6 (2008/11/15) この部分は不要なので元に戻します
    082                ExecThread oet = getExecThread( queue.getThreadId() );
    083//              ExecThread oet = getExecThread( queue.getSystemId() + "_" + queue.getThreadId() ); // 4.3.0.0 (2008/07/15) システムIDをスレッドIDに付加します。
    084                oet.stackQueue( queue );
    085        }
    086
    087        /**
    088         * キューを該当するスレッドにスタックする
    089         *
    090         * このメソッドでは、既に同じスレッドが存在するかどうかをチェックせずに必ず
    091         * 新しいスレッドを生成し、キューを処理します。
    092         * また、処理が完了した後、そのスレッドは、WAITすることなく終了します。
    093         *
    094         * @og.rev 5.1.6.0 (2010/05/01) 新規作成
    095         *
    096         * @param       queue   ExecQueueオブジェクト
    097         */
    098        public static void insertQueueOnNewThread( final ExecQueue queue ) {
    099                ExecThread oet = new ExecThread( queue.getThreadId(), debug );
    100                oet.start();
    101                System.out.println( "[INFO]THREAD CREATED:THREAD-ID=" + queue.getThreadId() );
    102                oet.stackQueue( queue );
    103                oet.finishAfterExec();
    104        }
    105
    106        /**
    107         * 該当するスレッドIDを持つスレッドを取得します。
    108         * スレッドプールに存在しない場合は、新規に作成されます。
    109         *
    110         * @param       threadId        スレッドID
    111         *
    112         * @return      ExecThreadスレッド
    113         */
    114        private static ExecThread getExecThread( final String threadId ) {
    115                ExecThread oet = null;
    116                synchronized( pool ) {
    117                        oet = pool.get( threadId );
    118
    119                        // スレッドが終了している場合は、再度作成
    120                        if( oet != null && !oet.isAlive() ) {
    121                                pool.remove( threadId );
    122                                oet = null;
    123                        }
    124
    125                        if( oet == null ) {
    126                                // oet = new ExecThread( threadId );
    127                                oet = new ExecThread( threadId, debug );
    128                                oet.start();
    129                                System.out.println( "[INFO]THREAD CREATED:THREAD-ID=" + threadId );
    130                                pool.put( threadId, oet );
    131                        }
    132                }
    133
    134                return oet;
    135        }
    136
    137        /**
    138         * 全てのスレッドを終了します。
    139         *
    140         */
    141        public static void finishAllThreads() {
    142                synchronized( pool ) {
    143                        for( ExecThread oet : pool.values() ) {
    144                                oet.finish();
    145                        }
    146                        pool.clear();
    147                        System.out.println( "[INFO]ALL THREADS FINISHED" );
    148                }
    149        }
    150
    151        /**
    152         * 指定のスレッドを終了します。
    153         *
    154         * @param threadId スレッドID
    155         */
    156        public static void finishThread( final String threadId ) {
    157                synchronized( pool ) {
    158                        ExecThread oet = pool.remove( threadId );
    159                        if( oet != null ) {
    160                                oet.finish();
    161                                System.out.println( "[INFO]THREAD CREATED:THREAD-ID=" + threadId );
    162                        }
    163                }
    164        }
    165
    166        /**
    167         * スレッド情報のマップを返します。
    168         *
    169         * @return      スレッド情報のマップ
    170         */
    171        public static Map<String, String> getThreadInfo() {
    172                Map<String, String> info = new HashMap<String, String>();
    173                synchronized( pool ) {
    174                        for( Map.Entry<String, ExecThread> entry : pool.entrySet() ) {
    175                                info.put( entry.getKey(), entry.getValue().toString() );
    176                        }
    177                }
    178                return info;
    179        }
    180
    181        /**
    182         * デバッグフラグの設定
    183         *
    184         * @og.rev  4.3.0.0 (2008/07/15) デバッグ追加
    185         *
    186         * @param   flag デバッグフラグ [true:デバッグ/false:通常]
    187         */
    188        public static void setDebug ( final boolean flag ){
    189                debug = flag;
    190        }
    191
    192//      /**
    193//       * 監視用のスレッドを開始します。
    194//       *
    195//       */
    196//      private static void checkThreads() {
    197//              new Thread() {
    198//                      public void run() {
    199//
    200//                              while( true ) {
    201//                                      try {
    202//                                              Thread.sleep( REPORT_THREAD_CHECK_INTERVAL );
    203//                                      }
    204//                                      catch( InterruptedException e ) {}
    205//
    206//                                      synchronized( pool ) {
    207//                                              for( Map.Entry<String, ExecThread> entry : pool.entrySet() ) {
    208//                                                      String id = entry.getKey();
    209//                                                      ExecThread oet = entry.getValue();
    210//
    211//                                                      System.out.println(oet.getExecTime());
    212//
    213//                                                      if( oet.getExecTime() > REPORT_THREAD_CRASH_TIME ) {
    214//                                                              System.out.println( "【監視】スレッドID=" + id + "がクラッシュしている可能性がありますので、割込要求を発行します。(処理時間=" + String.valueOf( oet.getExecTime() ) + ")" );
    215//                                                              oet.interrupt();
    216//                                                      }
    217//                                              }
    218//                                      }
    219//                              }
    220//
    221//                      }
    222//              }.start();
    223//      }
    224
    225}