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.ArrayList; 019import java.util.Collections; 020import java.util.List; 021 022import org.opengion.fukurou.system.ThrowUtil ; // 6.4.2.0 (2016/01/29) 023import org.opengion.hayabusa.common.HybsSystem; 024import static org.opengion.fukurou.system.HybsConst.CR ; // 6.1.0.0 (2014/12/26) 025import static org.opengion.fukurou.system.HybsConst.BUFFER_MIDDLE; // 6.1.0.0 (2014/12/26) refactoring 026 027/** 028 * 帳票要求スレッドの本体です。 029 * 外部からスタックされたキューを先入れ先出しの順番に処理します。 030 * 031 * あるキューに対してエラーが発生すると、システムリソースのRETRY_COUNTで設定された回数再処理を試みます。 032 * この回数分エラーが発生した場合は、そのキューのみがアプリエラーとなります。 033 * 034 * このスレッドは一度生成されると、外部から明示的に終了の要求を起こさない限り生存し続けます。 035 * 終了するには、finish()メソッドを呼び出します。 036 * このメソッドが呼ばれると、内部でスタックしているキューは全てクリアされるため、その時点で 037 * 処理されているキューの処理が完了した時点で、スレッドが終了します。 038 * 039 * @og.group 帳票システム 040 * 041 * @version 4.0 042 * @author Hiroki.Nakamura 043 * @since JDK1.6 044 */ 045public class ExecThread extends Thread { 046 047 /** ステータスの enum */ 048 private enum Status { EXECUTE, WAIT }; 049// private static enum Status { EXECUTE, WAIT }; 050 private Status state = Status.EXECUTE; 051 052 private static final int RETRY_COUNT = HybsSystem.sysInt( "REPORT_RETRY_COUNT" ); 053 054 private final List<ExecQueue> queues = Collections.synchronizedList( new ArrayList<>() ); 055 056 private long threadStart ; 057 private long execStart ; 058 private long execEnd ; 059 private final boolean debug; // 4.3.0.0 (2008/07/15) デバッグの追加 060 061 /** 062 * コンストラクタ 063 * OOoへの接続を生成します。 064 * 065 * @param id スレッドID 066 */ 067 public ExecThread( final String id ) { 068 // threadStart = System.currentTimeMillis(); 069 // setName( id ); // スタックトレース時にスレッドIDを出すためにセット 070 this ( id , false ); 071 } 072 073 /** 074 * コンストラクタ 075 * OOoへの接続を生成します。 076 * 077 * @og.rev 4.3.0.0 (2008/07/15) デバッグフラグを追加します。 078 * @og.rev 6.4.1.1 (2016/01/16) PMD refactoring. It is a good practice to call super() in a constructor 079 * 080 * @param id スレッドID 081 * @param debugFlag デバッグフラグ[true/false] 082 */ 083 public ExecThread( final String id , final boolean debugFlag ) { 084 super(); 085 threadStart = System.currentTimeMillis(); 086 setName( id ); // スタックトレース時にスレッドIDを出すためにセット 087 debug = debugFlag; // 4.2.5.0 (2008/06/26) デバッグ処理の追加 088 } 089 090 /** 091 * Map#compute で対応 出来るように、start() 実行後の 新規に作成した ExecThread を返します。 092 * 093 * @og.rev 6.4.3.3 (2016/03/04) Map#compute で対応する。 094 * 095 * @param id スレッドID 096 * @param debugFlag デバッグフラグ[true/false] 097 * @return startメソッド実行後の新規に作成したExecThreadオブジェクト 098 */ 099 public static final ExecThread startExecThread( final String id , final boolean debugFlag ) { 100 final ExecThread oet = new ExecThread( id, debugFlag ); 101 oet.start(); 102 return oet; 103 } 104 105 /** 106 * キューをスタックします。 107 * 108 * @og.rev 4.3.0.0 (2008/07/15) debug追加 109 * @param queue ExecQueueオブジェクト 110 * 111 * @return スタックが受け付けられたかどうか 112 */ 113 public boolean stackQueue( final ExecQueue queue ) { 114 queue.addMsg( "[INFO]QUEUE STACK:THREAD-ID=" + queue.getThreadId() + ",YKNO=" + queue.getYkno() + CR ); 115 116 queues.add( queue ); 117 118 queue.setExecute(); 119 if( debug ) { queue.addMsg( "[INFO]QUEUE STACKED" + CR ); } 120 121 synchronized( this ) { 122 if( state == Status.WAIT ) { 123 this.interrupt(); 124 if( debug ) { queue.addMsg( "[INFO]INTERRUPT" + CR ); } 125 } 126 } 127 return true; 128 } 129 130 /** 131 * このスレッドの実行を開始します。Java仮想マシンは、このスレッドのrunメソッドを呼び出します。 132 * 133 * ここでは、実行されたときのメッセージを表示するために、Override しています。 134 * 135 * @og.rev 6.4.3.3 (2016/03/04) 処理メッセージを表示します。 136 */ 137 @Override 138 public void start() { 139 System.out.println( "[INFO]THREAD CREATED:THREAD-ID=" + getName() ); 140 super.start(); 141 } 142 143 /** 144 * スレッド本体 145 * スタックされたキューを順番に取り出し処理を行います。 146 */ 147 @Override 148 public void run() { 149 while( true ) { 150 synchronized( this ) { 151 while( queues.isEmpty() ) { 152 try { 153 state = Status.WAIT; 154 wait(); 155 } 156 catch( final InterruptedException ex ) { 157 state = Status.EXECUTE; 158 } 159 } 160 } 161 162 final ExecQueue queue = popQueue(); 163 if( queue != null ) { 164 if( "_FINALIZE".equals( queue.getYkno() ) ) { 165 if( debug ) { queue.addMsg( "[INFO]END" + CR ); } 166 break; 167 } 168 else { 169 if( debug ) { queue.addMsg( "[INFO]QUEUE START" + CR ); } 170 exec( queue ); 171 172 // System.out.println( queue.getMsg() ); 173 System.out.print( queue.getMsg() ); // 4.3.0.0 (2008/07/15) 174 } 175 } 176 } 177 } 178 179 /** 180 * スレッドを終了させるためのキューを追加します。 181 * 182 * このメソッドが呼ばれると、内部にスタックしているキューは全てクリアされます。 183 * 184 * @og.rev 6.4.3.3 (2016/03/04) 処理メッセージを表示します。 185 */ 186 public void finish() { 187 queues.clear(); 188 189 System.out.println( "[INFO]THREAD CREATED:THREAD-ID=" + getName() ); 190 191 final ExecQueue qu = new ExecQueue(); 192 qu.setYkno( "_FINALIZE" ); 193 stackQueue( qu ); 194 } 195 196 /** 197 * スレッドを終了させるためのキューを追加します。 198 * 199 * このメソッドでは、既にスタックされているキューはクリアされず、全て処理された後で、 200 * スレッドを終了します。 201 * 202 * @og.rev 5.1.6.0 (2010/05/01) 新規作成 203 */ 204 public void finishAfterExec() { 205 final ExecQueue qu = new ExecQueue(); 206 qu.setYkno( "_FINALIZE" ); 207 stackQueue( qu ); 208 } 209 210 /** 211 * 帳票処理を行います。 212 * 213 * @og.rev 5.1.2.0 (2010/01/01) 256シートを超えた場合でも、正しく処理できるように対応 214 * 215 * @param queue ExecQueueオブジェクト 216 */ 217 private void exec( final ExecQueue queue ) { 218 execStart = System.currentTimeMillis(); 219 220 final ExecProcess oep = new ExecProcess( queue, debug ); 221 for( int i=0; i <= RETRY_COUNT; i++ ) { 222 try { 223 // 5.1.2.0 (2010/01/01) データが終わるまで処理を継続する。 224 while( !queue.isEnd() ) { 225 oep.process(); 226 } 227 queue.setComplete(); 228 break; 229 } 230 catch( final Throwable th ) { 231 queue.addMsg( "[ERROR]ERROR OCCURRED!" + CR ); 232 queue.addMsg( ThrowUtil.ogStackTrace( th ) ); // 6.4.2.0 (2016/01/29) 233 234 if( i == RETRY_COUNT ) { 235 queue.addMsg( "[ERROR]UPTO RETRY COUNT!" + CR ); 236 queue.setError(); 237 } 238 } 239 } 240 241 execEnd = System.currentTimeMillis(); 242 } 243 244 /** 245 * キューを取り出します。 246 * 247 * @return キュー 248 */ 249 private ExecQueue popQueue() { 250 return queues.remove( 0 ); 251 } 252 253 /** 254 * このクラスの文字列表現を返します。 255 * 256 * @og.rev 4.3.0.0 (2008/07/15) debugを追加 257 * 258 * @return 文字列表現 259 * @og.rtnNotNull 260 */ 261 @Override 262 public String toString() { 263 final StringBuilder buf = new StringBuilder( BUFFER_MIDDLE ) 264 .append( "STATE=" ).append( state.toString() ) 265 .append( ", START=" ).append( HybsSystem.getDate( threadStart ) ) 266 .append( ", POOL=" ).append( queues.size() ) 267 .append( ", EXEC-START=" ).append( HybsSystem.getDate( execStart ) ) 268 .append( ", EXEC-END=" ).append( HybsSystem.getDate( execEnd ) ) 269 .append( ", DEBUG=" ).append( debug ); // 4.3.0.0 (2008/07/15) デバッグの追加 270 271 return buf.toString(); 272 } 273}