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) 020import org.opengion.fukurou.util.Cleanable; // 8.5.6.0 (2024/02/29) 021import org.opengion.hayabusa.common.SystemManager; // 8.5.6.0 (2024/02/29) 022 023/** 024 * 帳票処理を行う各スレッドを管理するクラスです。 025 * 026 * 各スレッドは、内部的にプールされます。 027 * スレッドのIDはOOoQueue#getThreadId()で返される値です。 028 * スレッドが生成されるタイミングは、そのIDで初めてスタック要求が来た(insertQueue()が呼ばれた)時です。 029 * 030 * 指定のスレッドを終了するには、funishThread( key )を呼び出します。 031 * 全てのスレッドを終了するには、funishAllThreads()を呼び出します。 032 * 033 * 現時点での実装では、生成されたスレッドに対しての監視は行っていません。 034 * これは、特定のスレッドがフリーズした際、外部から強制終了を行おうとすると、 035 * 監視スレッドもフリーズしてしまう問題があるためです。 036 * (但し、1つのsoffice.binのプロセスに対してシリアルに対して処理している限りでは、 037 * フリーズ問題は発生しないようです) 038 * 039 * @og.group 帳票システム 040 * 041 * @version 4.0 042 * @author Hiroki.Nakamura 043 * @since JDK1.6 044 */ 045public final class ExecThreadManager { 046 /** 6.4.3.1 (2016/02/12) 一連の処理で同期を取りたいので、 ConcurrentHashMap は使いません。 */ 047 private static final ConcurrentMap<String, ExecThread> EXEC_POOL = new ConcurrentHashMap<>(); // 6.4.3.3 (2016/03/04) 048 private static boolean debug ; // 4.3.0.0 (2008/07/15) デバッグ追加 049 050 /** 8.5.6.0 (2024/02/29) common/HybsContextListener から移動 */ 051 static { 052 final Cleanable clr = new Cleanable() { 053 /** 054 * 全てのスレッドを終了します。 055 */ 056 public void clear() { 057 // 8.5.6.1 (2024/03/29) REP21/result2.jsp で、使用していたので復活。 058 finishAllThreads(); 059// EXEC_POOL.forEach( (id,oet) -> oet.finish() ); 060// System.out.println( "[INFO]ALL THREADS FINISHED" ); 061 } 062 }; 063 SystemManager.addCleanable( clr,true ); // contextDestroyed の場合のみ実行 064 } 065 066 /** 067 * デフォルトコンストラクターをprivateにして、 068 * オブジェクトの生成をさせないようにする。 069 */ 070 private ExecThreadManager() {} 071 072 /** 073 * キューを該当するスレッドにスタックする。 074 * 075 * @og.rev 4.3.0.0 (2008/07/15) スレッドIDにシステムIDを付加 076 * 077 * @param queue ExecQueueオブジェクト 078 */ 079 public static void insertQueue( final ExecQueue queue ) { 080 // 4.3.3.6 (2008/11/15) この部分は不要なので元に戻します 081 final ExecThread oet = getExecThread( queue.getThreadId() ); 082 oet.stackQueue( queue ); 083 } 084 085 /** 086 * キューを該当するスレッドにスタックする 087 * 088 * このメソッドでは、既に同じスレッドが存在するかどうかをチェックせずに必ず 089 * 新しいスレッドを生成し、キューを処理します。 090 * また、処理が完了した後、そのスレッドは、WAITすることなく終了します。 091 * 092 * @og.rev 5.1.6.0 (2010/05/01) 新規作成 093 * 094 * @param queue ExecQueueオブジェクト 095 */ 096 public static void insertQueueOnNewThread( final ExecQueue queue ) { 097 final ExecThread oet = new ExecThread( queue.getThreadId(), debug ); 098 oet.start(); 099 oet.stackQueue( queue ); 100 oet.finishAfterExec(); 101 } 102 103 /** 104 * 該当するスレッドIDを持つスレッドを取得します。 105 * スレッドプールに存在しない場合は、新規に作成されます。 106 * 107 * @og.rev 6.4.3.3 (2016/03/04) Map#compute で対応する。 108 * 109 * @param threadId スレッドID 110 * 111 * @return ExecThreadスレッド 112 */ 113 private static ExecThread getExecThread( final String threadId ) { 114 // Map#compute : 戻り値は、新しい値。追加有り、置換有り、削除有り 115 return EXEC_POOL.compute( threadId, (id,oet) -> 116 oet == null || !oet.isAlive() ? ExecThread.startExecThread( id, debug ) : oet ); 117 } 118 119 /** 120 * 全てのスレッドを終了します。 121 * 122 * ※ REP21/result2.jsp で、使用。 123 * 124 * @og.rev 6.4.3.3 (2016/03/04) Map#forEach で対応する。 125 * @og.rev 8.5.6.0 (2024/02/29) common/HybsContextListener から移動。 126 * @og.rev 8.5.6.1 (2024/03/29) REP21/result2.jsp で、使用していたので復活。 127 */ 128 public static void finishAllThreads() { 129 EXEC_POOL.forEach( (id,oet) -> oet.finish() ); 130 System.out.println( "[INFO]ALL THREADS FINISHED" ); 131 } 132 133 /** 134 * 指定のスレッドを終了します。 135 * 136 * ※ REP21/entry.jsp で、使用。 137 * 138 * @param threadId スレッドID 139 */ 140 public static void finishThread( final String threadId ) { 141 final ExecThread oet = EXEC_POOL.remove( threadId ); 142 // Map上には null はないが、キーが合わない場合は、null が戻る。 143 if( oet != null ) { 144 oet.finish(); 145 System.out.println( "[INFO]THREAD CREATED:THREAD-ID=" + threadId ); 146 } 147 } 148 149 /** 150 * スレッド情報のマップを返します。 151 * 152 * ※ REP21/result2.jsp で、使用。 153 * 154 * @og.rev 6.4.3.1 (2016/02/12) PMD refactoring. HashMap → ConcurrentHashMap に置き換え。 155 * @og.rev 6.4.3.3 (2016/03/04) 戻すMapが、not null制限つきであることを示すため、ConcurrentMap に置き換えます。 156 * @og.rev 6.4.3.3 (2016/03/04) Map#forEach で対応する。 157 * 158 * @return スレッド情報のマップ 159 */ 160 public static ConcurrentMap<String, String> getThreadInfo() { 161 final ConcurrentMap<String, String> infoMap = new ConcurrentHashMap<>(); 162 163 EXEC_POOL.forEach( (id,oet) -> infoMap.put( id,oet.toString() ) ); 164 165 return infoMap; 166 } 167 168 /** 169 * デバッグフラグの設定。 170 * 171 * @og.rev 4.3.0.0 (2008/07/15) デバッグ追加 172 * 173 * @param flag デバッグフラグ [true:デバッグ/false:通常] 174 */ 175 public static void setDebug ( final boolean flag ){ 176 debug = flag; 177 } 178}