0

내 응용 프로그램에서 작업을 생성하는 복수 scheduler 스레드가 있습니다. 예를 를 들어 각 스케줄러 스레드 작업의 무리를 만들 수 있습니다다중 일정 스레드 제출 작업 RejectedExecutionException

당신이 로그에서 볼 수 있듯이 스케줄러 스레드를 동시에 실행할 수 있습니다
TaskCreator tastCreator; 
for (Report report: report) { 
    taskCreator.createTask(report); 
} 

:

15:57:20.107 INFO [ scheduler-4] c.task.ReportExportSchedulerTask : Task created 
15:57:20.107 INFO [ scheduler-2] c.task.ReportExportSchedulerTask : Task created 

을 전달하는 다음과 같이 나는 TaskCreator 구성 요소가 executeJob()에 작업 :

@Component 
public class TaskCreator { 
    @Autowired 
    private SftpTaskExecutor sftpTaskExecutor; 
    @Autowired 
    SftpConfig sftpConfig; 

    @Autowired 
    private SFTPConnectionManager connectionManager; 

    public void createTask(Report report) { 
     sftpTaskExecutor.executeJob(new JobProcessorTask(...)); 
    } 

    public void validateTasksExecution() { 
     sftpTaskExecutor.getExecutorService().shutdown(); 
     while (!sftpTaskExecutor.getExecutorService().isTerminated()) ; 
     connectionManager.disconnect(); 
    } 
} 

SftpTaskExecutor,643,executorService이있는 I가 위의 작업을 제출 구축이 다음과 같이 두 개 이상의 스케줄러 스레드가 작업을 생성하고 동시에 서비스를 집행하기 위해 제출하는 경우

@Component 
public class SftpTaskExecutor { 
    private ExecutorService executorService = Executors.newSingleThreadExecutor(); 

    public void executeJob(JobProcessorTask jobProcessorTask) { 
     executorService.execute(jobProcessorTask); 
    } 

    public ExecutorService getExecutorService() { 
     return executorService; 
    } 
} 

내 질문은, 위가 RejectedExecutionException를 throw한다 하나의 스케줄러 태스크가 완료되지 않음 (즉, 파일이 전송되지 않음)

일정 스레드마다 다른 스케줄러 스레드와 간섭하지 않고 validateTasksExecution()을 호출 할 수 있어야합니다. 다른 말로하면 다른 스케줄러가 아직 처리 중일 때 연결을 끊지 마십시오.

여기에서 ExecutorService을 올바르게 사용하고 있습니까? 위의 내용을 스레드로부터 안전하게 변경하려면 어떻게해야합니까? 두 개 이상의 스케줄러 스레드가 작업을 생성하고 동시에 서비스를 집행하기 위해 제출하는 경우

+0

도움이 되었다면 답변을 수락하십시오. – Gray

답변

0

내 질문은, 위에서 언급 한 (즉,이 전송되지 파일)을 하나의 스케줄러 작업이 완료되지

하자가있는 RejectedExecutionException를 throw한다 javadocs for ExecutorService.execute(...)

RejectedExecutionException - 실행을 위해이 작업을 수락 할 수없는 경우를 살펴보십시오. ThreadPoolExecutor (와 관련된) 코드를 찾고에서

, 작업은 2 이유로 거부 얻을 :

  • 작업에 대한 큐 (큐이기 때문에이 사항이 적용되지 않습니다 가득 무제한의 기본)
  • 집행자 서비스가 더 이상 실행
  • (땡 땡 땡)

에 의해 나는 당신의 스레드의 첫 번째가 있기 때문에 당신의 유언 집행 서비스가 가장 가능성이 종료되었다고 생각 두 번째 스레드가 executeJob(...)을 호출하기 전에 validateTasksExecution()이라고합니다. 해당 스레드 풀을 다시 사용하려는 경우 코드가 올바르지 않습니다. 또한 connectionManager()을 닫으면 SftpTaskExecutor을 다시 사용 하시겠습니까?

당신의 작업이 완료되면 각 스레드가보고 싶어하지만 당신은 ExecutorService.submit(...) 방법에서 Future(s)을 절약하고 그들에 get()를 호출 할 필요가 다음 실행되는 스레드 풀 숙박을합니다. 그 일이 언제 끝날 지 알려줄 것입니다. 같은

뭔가 :

public Future<Void> createTask(Report report) { 
    return sftpTaskExecutor.executeJob(new JobProcessorTask(...)); 
} 

public void validateTasksExecution(Future<Void> future) { 
    // there is some exceptions here you need to handle 
    future.get(); 
} 

public void shutdown() { 
    sftpTaskExecutor.shutdown(); 
    connectionManager.disconnect(); 
} 

... 

public Future<Void> executeJob(JobProcessorTask jobProcessorTask) { 
    return executorService.submit(jobProcessorTask); 
} 

당신이 다음 모음에 저장해야 여러 작업을 모니터링하고 작업이 병렬로 실행 되더라도 순차적으로 그들에 get()를 호출해야하는 경우

.

다른 방법으로는 각 트랜잭션마다 별도의 ExecutorService을 가질 수 있습니다. 이는 낭비 적이지만 sftp 호출을 관리하는 것을 고려할 때 그리 좋지 않을 수 있습니다.

while (!sftpTaskExecutor.getExecutorService().isTerminated()) ; 

그래 당신은 그런 식으로 회전하지 않습니다. awaitTermination(...) javadocs을 참조하십시오.