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