web-dev-qa-db-ja.com

`ThreadPoolTask​​Executor`スレッドはSpringでの実行後に強制終了されません

QuartzSequential実行をParallelExecutionに変更しようとしています。

正常に動作しています。パフォーマンスに関しては、問題はないようですが、生成された(作成された)スレッドは破棄されません。

まだRunnable状態です。なぜそしてどうすればそれを修正できますか?案内してください。

enter image description here

コードはここにあります:

    @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);
}
}

必要に応じてスレッドダンプファイルを提供できます。

10
ThinkTank

スレッドの優先度を上げ、プロセッサのコア数に応じてスレッド数を作成する必要があります。

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();
        }
}
0
ThinkTank

スレッドの1つがIO要求の応答を無期限に待機していると思われます。たとえば、接続タイムアウトを設定していないリモートホストに接続しようとして、ホストが応答しません。この場合、基になるshutdownNowExecutorServiceメソッドを実行することで、実行中のすべてのタスクを強制的にシャットダウンできます。次に、問題のあるスレッドによってスローされた InterruptedIOException を分析できます。

交換

threadPoolExecuter.shutdown();

以下でエラーを調べることができます。

ExecutorService executorService = threadPoolExecuter.getThreadPoolExecutor();
executorService.shutdownNow();

これにより、実行中のすべてのスレッドに 割り込み 信号が送信されます。

3
Root G

同じサイズの試験でスレッドプールを作成しているようですが、これは最適ではありません。

    // Core pool size is = number of exams  
    threadPoolExecuter.setCorePoolSize(lstOfExams.size());

    // Max pool size is just 1 + exam size. 
    threadPoolExecuter.setMaxPoolSize(lstOfExams.size()+1);

次の点を考慮する必要があります。-スレッドプールを作成して開始した場合、コアサイズで定義されている数のスレッドがすぐに開始されます。

  • 最大プールサイズは、コアプールスレッドが現在処理できる以上の数を送信した場合、およびキューサイズがいっぱい(この場合は100)の場合にのみ有効です。つまり、送信されたタスクの数が100以上の試験サイズを超えた場合にのみ、新しいスレッドが作成されます。

あなたの場合、コアプールのサイズを5または10に設定します(実際には、ターゲットCPUのコア数や、送信されたタスクのIOバウンドの程度によって異なります)。

最大プールサイズはその2倍にすることができますが、キューがいっぱいになるまで有効になりません。

送信された作業が完了した後にライブスレッドのサイズを小さくするには、2つのパラメーターを設定する必要があります。

  • setKeepAliveSeconds(int keepAliveSeconds):定義された秒(デフォルトでは60秒が最適)に沿って使用されない場合、スレッドを自動的にシャットダウンしますが、これは通常、のスレッドをシャットダウンするためにのみ使用されます非コアプールスレッド。

  • KeepAliveSecondsの後にコア部分のスレッドをシャットダウンするには、setAllowCoreThreadTimeOut(boolean allowCoreThreadTimeOut)をtrueに設定する必要があります。これは通常、アプリケーションが実行されている限りコアプールを存続させるために誤りです。

お役に立てば幸いです。

3
Selim Ok

スレッドで実行されるメソッドは一部のjdbcドライバークラスに含まれるため、スレッドはリモートサーバーからのIOを待機しませんが、現在はすべてUpdateUserExamDataThread.run()の37行目にあります。 。

ここで問題は、UpdateUserExamDataThread.Javaの37行目のコードは何ですか?残念ながら、現時点で提供されているUpdateUserExamDataThread.Javaは不完全であるか、実際に実行されたバージョンではありません。パッケージ宣言が欠落しており、29行目で終了しています。

0
evernat

問題は、submit()を使用してタスクスレッドを生成するときにexecute()ではなくrun()を呼び出していることだと思います。 submitを使用する場合、runメソッドの最後で終了するのではなく、タスクが終了するとスレッドが自殺するという期待がおそらくあります。

0
AardvarkBlue