QuartzSequential実行をParallelExecutionに変更しようとしています。
正常に動作しています。パフォーマンスに関しては、問題はないようですが、生成された(作成された)スレッドは破棄されません。
まだRunnable
状態です。なぜそしてどうすればそれを修正できますか?案内してください。
コードはここにあります:
@Override
protected void executeInternal(JobExecutionContext context) throws JobExecutionException {
logger.error("Result Processing executed");
List<Object[]> lstOfExams = examService.getExamEntriesForProcessingResults();
String timeZone = messageService.getMessage("org.default_timezone", null, Locale.getDefault());
if(lstOfExams!=null&&!lstOfExams.isEmpty()){
ThreadPoolTaskExecutor threadPoolExecuter = new ThreadPoolTaskExecutor();
threadPoolExecuter.setCorePoolSize(lstOfExams.size());
threadPoolExecuter.setMaxPoolSize(lstOfExams.size()+1);
threadPoolExecuter.setBeanName("ThreadPoolTaskExecutor");
threadPoolExecuter.setQueueCapacity(100);
threadPoolExecuter.setThreadNamePrefix("ThreadForUpdateExamResult");
threadPoolExecuter.initialize();
for(Object[] obj : lstOfExams){
if(StringUtils.isNotBlank((String)obj[2]) ){
timeZone = obj[2].toString();
}
try {
Userexams userexams=examService.findUserExamById(Long.valueOf(obj[0].toString()));
if(userexams.getExamresult()==null){
UpdateUserExamDataThread task=new UpdateUserExamDataThread(obj,timeZone);
threadPoolExecuter.submit(task);
}
// testEvaluator.generateTestResultAsPerEvaluator(Long.valueOf(obj[0].toString()), obj[4].toString(), obj[3]==null?null:obj[3].toString(),timeZone ,obj[5].toString() ,obj[1].toString());
// logger.error("Percentage Marks:::::"+result.getPercentageCatScore());
} catch (Exception e) {
Log.error("Exception at ResultProcessingJob extends QuartzJobBean executeInternal(JobExecutionContext context) throws JobExecutionException",e);
continue;
}
}
threadPoolExecuter.shutdown();
}
}
UpdateUserExamDataThread .class
@Component
//@Scope(value="prototype", proxyMode=ScopedProxyMode.TARGET_CLASS)
//public class UpdateUserExamDataThread extends ThreadLocal<String> //implements Runnable {
public class UpdateUserExamDataThread implements Runnable {
private Logger log = Logger.getLogger(UpdateUserExamDataThread.class);
@Autowired
ExamService examService;
@Autowired
TestEvaluator testEvaluator;
private Object[] obj;
private String timeZone;
public UpdateUserExamDataThread(Object[] obj,String timeZone) {
super();
this.obj = obj;
this.timeZone = timeZone;
}
@Override
public void run() {
String threadName=String.valueOf(obj[0]);
log.info("UpdateUserExamDataThread Start For:::::"+threadName);
testEvaluator.generateTestResultAsPerEvaluator(Long.valueOf(obj[0].toString()), obj[4].toString(), obj[3]==null?null:obj[3].toString(),timeZone ,obj[5].toString() ,obj[1].toString());
//update examResult
log.info("UpdateUserExamDataThread End For:::::"+threadName);
}
}
TestEvaluatorImpl.Java
@Override
@Transactional
public Examresult generateTestResultAsPerEvaluator(Long userExamId, String evaluatorType, String codingLanguage,String timeZoneFollowed ,String inctenceId ,String userId) {
dbSchema = messageService.getMessage("database.default_schema", null, Locale.getDefault());
try {
//Some Methods
return examResult;
}catch(Exception e){
log.erorr(e);
}
}
必要に応じてスレッドダンプファイルを提供できます。
スレッドの優先度を上げ、プロセッサのコア数に応じてスレッド数を作成する必要があります。
protected void executeInternal(JobExecutionContext context) throws JobExecutionException {
logger.error("Result Processing executed");
List<Object[]> lstOfExams = examService.getExamEntriesForProcessingResults();
String timeZone = messageService.getMessage("org.default_timezone", null, Locale.getDefault());
int cores = Runtime.getRuntime().availableProcessors();
if(lstOfExams!=null&&!lstOfExams.isEmpty()){
ThreadPoolTaskExecutor threadPoolExecuter = new ThreadPoolTaskExecutor();
threadPoolExecuter.setCorePoolSize(cores);
// threadPoolExecuter.setMaxPoolSize(Integer.MAX_VALUE);
threadPoolExecuter.setBeanName("ThreadPoolTaskExecutor");
// threadPoolExecuter.setQueueCapacity(Integer.MAX_VALUE);
threadPoolExecuter.setQueueCapacity(lstOfExams.size()+10);
threadPoolExecuter.setThreadNamePrefix("ThreadForUpdateExamResult");
threadPoolExecuter.setWaitForTasksToCompleteOnShutdown(true);
threadPoolExecuter.setThreadPriority(10);
threadPoolExecuter.initialize();
for(Object[] obj : lstOfExams){
if(StringUtils.isNotBlank((String)obj[2]) ){
timeZone = obj[2].toString();
}
try {
Userexams userexam=examService.findUserExamById(Long.valueOf(obj[0].toString()));
if(userexam.getExamresult()==null){
UpdateUserExamDataThread task=new UpdateUserExamDataThread(obj,timeZone,testEvaluator);
// threadPoolExecuter.submit(task);
threadPoolExecuter.execute(task);
}
// testEvaluator.generateTestResultAsPerEvaluator(Long.valueOf(obj[0].toString()), obj[4].toString(), obj[3]==null?null:obj[3].toString(),timeZone ,obj[5].toString() ,obj[1].toString());
// logger.error("Percentage Marks:::::"+result.getPercentageCatScore());
} catch (Exception e) {
logger.error("Exception at ResultProcessingJob extends QuartzJobBean executeInternal(JobExecutionContext context) throws JobExecutionException",e);
continue;
}
}
threadPoolExecuter.shutdown();
}
}
スレッドの1つがIO要求の応答を無期限に待機していると思われます。たとえば、接続タイムアウトを設定していないリモートホストに接続しようとして、ホストが応答しません。この場合、基になるshutdownNow
のExecutorService
メソッドを実行することで、実行中のすべてのタスクを強制的にシャットダウンできます。次に、問題のあるスレッドによってスローされた InterruptedIOException を分析できます。
交換
threadPoolExecuter.shutdown();
以下でエラーを調べることができます。
ExecutorService executorService = threadPoolExecuter.getThreadPoolExecutor();
executorService.shutdownNow();
これにより、実行中のすべてのスレッドに 割り込み 信号が送信されます。
同じサイズの試験でスレッドプールを作成しているようですが、これは最適ではありません。
// Core pool size is = number of exams
threadPoolExecuter.setCorePoolSize(lstOfExams.size());
// Max pool size is just 1 + exam size.
threadPoolExecuter.setMaxPoolSize(lstOfExams.size()+1);
次の点を考慮する必要があります。-スレッドプールを作成して開始した場合、コアサイズで定義されている数のスレッドがすぐに開始されます。
あなたの場合、コアプールのサイズを5または10に設定します(実際には、ターゲットCPUのコア数や、送信されたタスクのIOバウンドの程度によって異なります)。
最大プールサイズはその2倍にすることができますが、キューがいっぱいになるまで有効になりません。
送信された作業が完了した後にライブスレッドのサイズを小さくするには、2つのパラメーターを設定する必要があります。
setKeepAliveSeconds(int keepAliveSeconds):定義された秒(デフォルトでは60秒が最適)に沿って使用されない場合、スレッドを自動的にシャットダウンしますが、これは通常、のスレッドをシャットダウンするためにのみ使用されます非コアプールスレッド。
KeepAliveSecondsの後にコア部分のスレッドをシャットダウンするには、setAllowCoreThreadTimeOut(boolean allowCoreThreadTimeOut)をtrueに設定する必要があります。これは通常、アプリケーションが実行されている限りコアプールを存続させるために誤りです。
お役に立てば幸いです。
スレッドで実行されるメソッドは一部のjdbcドライバークラスに含まれるため、スレッドはリモートサーバーからのIOを待機しませんが、現在はすべてUpdateUserExamDataThread.run()の37行目にあります。 。
ここで問題は、UpdateUserExamDataThread.Javaの37行目のコードは何ですか?残念ながら、現時点で提供されているUpdateUserExamDataThread.Javaは不完全であるか、実際に実行されたバージョンではありません。パッケージ宣言が欠落しており、29行目で終了しています。
問題は、submit()を使用してタスクスレッドを生成するときにexecute()ではなくrun()を呼び出していることだと思います。 submitを使用する場合、runメソッドの最後で終了するのではなく、タスクが終了するとスレッドが自殺するという期待がおそらくあります。