2016-10-29 2 views
1

스프링 웹 애플리케이션 안에 5 분마다 호출되는 예약 된 작업이 있습니다. @ scheduled tasks 작업을 종료하는 방법은 무엇입니까?

@Scheduled(fixedDelay = 300000) 
    public void importDataTask() 
{ 
    importData(); //db calls, file manipulations, etc.. 
} 

는 보통 작업 일 동안 원활하게 실행하지만, 때로는 예 방법 importaData(), 그래서 importDataTask() 다시 호출되지 않습니다 종료되지 않습니다 내가 응용 프로그램을 다시 시작할 때까지 모든 차단됩니다 발생합니다.

질문은 : 메소드가 무기한으로 차단되지 않을 것임을 확신 할 수있는 방법이 있습니까? (리소스 또는 다른 것을 기다리는 방식으로)?

+0

교착 상태를 찾는 것이 더 나은 방법이 될 것입니다. 그래서 우리가 수정을위한 아이디어를 제공 할 수 있을지는 의문입니다. –

답변

1

질문은 : 방법 무기한 (waybe 자원을 기다리고, 또는 다른 뭔가를) 차단되지 않습니다 있는지 확인하는 feasibile 방법이있다?

일정한 일정 간격으로 일정을 계획 할 수없는 경우 고정 지연을 사용하지 말고 지연 + 최종 실행 완료라는 두 가지 조건을 사용해야합니다.
두 조건이 충족되는지 확인하는 작업을 예약 할 수 있으며,이 경우 중요한 처리를 실행합니다. 그렇지 않으면 다음 일정을 기다립니다.
이렇게하면 차단해서는 안됩니다. 작업이 고정 지연을 초과하면 얼마 동안 기다릴 수 있습니다. 고정 지연이 자주 초과되어 문제가되는 경우 고정 지연을 사용하지 않아야하므로 일반적이지 않으므로 민감하게 증가시켜야합니다. 여기

은 (편집없이 서면 어떤 실수하는 경우 죄송합니다.) :

private boolean isLastImportDataTaskFinished; 

@Scheduled(fixedDelay = 300000) 
public void importDataTaskManager(){ 
    if (isLastImportDataTaskFinished()){ 
     new Thread(new ImportantDataProcessing())).start();   
    } 
    else{ 
     // log the problem if you want 
    } 
} 

private isLastImportDataTaskFinished(){ 
    // to retrieve this information, you can do as you want : use a variable 
    // in this class or a data in database,file... 
    // here a simple implementation 
    return isLastImportDataTaskFinished; 
} 

의 Runnable 클래스 :

public class ImportantDataProcessing implements Runnable{ 
    public void run(){  
     importData(); //db calls, file manipulations, etc..  
    } 
} 

코멘트 :

하지만 실행하는 경우 스레드로 어떻게하면 그것을 초과 찾을 수있는 그것을 죽일 수 이후 아무런 언급이 없으므로 시간 제한이 적용됩니다 ( 두 번째 작업을 사용하여 고정 된 상태를 파악할 수 있음).

ExecutorService를 사용할 수 있습니다 (여기에 대한 질문이 있습니다 : How to timeout a thread). 다음은 아주 간단한 예를

: 흥미로운 정보가 ImportantDataProcessing 처리에 의해 반환 될 수 있습니다

ExecutorService executor = Executors.newSingleThreadExecutor(); 
Future future = executor.submit(new ImportantDataProcessing()); 
try { 
    future.get(100, TimeUnit.SECONDS); 
} 
catch (InterruptedException e) { 
    e.printStackTrace(); 
} 
catch (ExecutionException e) { 
    e.printStackTrace(); 
} 
catch (TimeoutException e) { 
    // the timeout to handle but other exceptions should be handled :) 
    e.printStackTrace(); 
} 
executor.shutdown(); 

경우에, 당신은 미래를 입력하는 대신 실행 가능한 인스턴스의 작업을 할 수 있습니다.

+0

고마워요 @ davidxxx, 나는 의심의 여지가있다. 어떤 이유로 importData() 메소드가 블록 된 경우, fixedDelay는 이전 배치가 종료 될 때까지 대기하므로 importDataTask()의 ​​다음 반복은 호출되지 않습니다. 이 방법으로이 값 (db)을 확인하기위한 두 번째 작업 만 수행 할 수 있고 너무 많은 시간이 지나가고 있는지 확인할 수 있으므로 마지막 가져 오기 날짜를 기록하는 것이 좋습니다. 하지만? 어쩌면 내가 스레드 기능을 조사해야합니다. – frankieta

+1

사실. 이를 방지하기 위해 새 스레드에서 importData()를 실행할 수 있습니다. 이런 식으로 importDataTaskManager()가 차단되지 않습니다. 내 대답을 업데이 트 :) 그러나, importData() 종료되지 않을 경우, 문제가 훨씬 더 심각합니다. 두 번째 작업을 사용하는 것도 좋은 방법입니다. – davidxxx

+0

확실히 시도해 보겠습니다. 가져올 데이터가 거대 할 수 있기 때문에 처음으로 작업을 실행할 때마다 데이터를 청크로 나누어 한 번에 가져올 것이라고 생각합니다. 하지만 스레드로 실행하는 경우 (제한된 상태를 결정하는 두 번째 작업을 사용한다는 아이디어에서) 그것에 대한 참조가 없으므로 시간 제한을 초과한다고 판단하면 어떻게 죽일 수 있습니까? 죄송 합니다만 원래 질문에 대해 조종하고 있다면. – frankieta

0

먼저 확실합니다. 프로세스에 차단 된 로그/메시지/전자 메일과 같은 코드가 포함 된 경우 많은 생각할 수있는 방법이 있습니다.

두 번째로 차단할지 여부에 따라 결정됩니다. 블록이 의도하지 않는다면, 새로운 쓰레드 또는 타임 아웃이 선택 될 수 있습니다.

+0

예, 블록이 제 의도는 아닙니다. 제한된 시간 간격 (5 분)은 사용자가 반 실제 시간에 가져 오기 결과를보고 싶어하기 때문입니다. – frankieta

관련 문제