2016-10-29 2 views
1

внутри весеннего веб-приложения У меня запланированная задача, которая вызывается каждые пять минут.Как быть уверенным, что завершена задача @scheduled?

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

Обычно эта задача выполняется плавно в течение нескольких дней, но иногда бывает, что пример метода importaData() не прекращается, так importDataTask() не будет вызываться снова, и все будет заблокирован, пока не перезапустить приложение.

Вопрос заключается в следующем: существует ли способ, чтобы быть уверенным в том, что метод не будет блокироваться неограниченно (waybe ждет ресурс или что-то еще)?

+0

Нахождение тупика будет лучшим подходом, мы не знаем, где его поражают. поэтому я сомневаюсь, что мы можем предоставить идеи для исправления. –

ответ

1

Возникает вопрос: есть ли feasibile метод, чтобы быть уверенным, что метод не будет до бесконечности заблокирован (waybe ждет ресурса, или что-то еще)?

Если планирование не может быть запланировано с точным регулярным интервалом, возможно, вы не можете использовать фиксированную задержку, но использовать два условия: задержка + последнее выполнение.
Вы можете запланировать задачу, которая проверяет выполнение двух условий, и если это так, вы выполняете важную обработку. В противном случае он ждет следующего графика.
Таким образом, вы не должны блокироваться. Вы можете подождать некоторое время, если задача превысит фиксированную задержку. Если это проблема, потому что фиксированная задержка часто превышается, вам, вероятно, не следует использовать фиксированную задержку или, следовательно, вы должны повысить ее чувствительность, чтобы она была менее распространена.

Вот пример (запись без редактора Извините, если какая-то ошибка.):

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).

Вот очень простой пример:

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(); 

Если интересная информация может быть возвращена ImportantDataProcessing обработки, вы можете использовать задачу вместо работоспособных например ввести в будущее.

+0

Спасибо @davidxxx, у меня есть сомнения. Если метод importData() заблокирован по какой-либо причине, следующая итерация importDataTask() не будет вызываться, так как fixedDelay будет ждать завершения предыдущей партии, поскольку она не является параллельной. Идея регистрации последней даты импорта хороша, так как таким образом у меня могла бы быть задача SECOND только для проверки этого значения (из db) и посмотреть, прошло слишком много времени, поэтому я могу интерпретировать ее как застрявшую. Но потом? Может быть, я должен посмотреть на функции Threads. – frankieta

+1

Действительно. Чтобы этого избежать, вы можете запустить importData() в новой теме. Таким образом importDataTaskManager() не будет блокировать. Я обновляю свой ответ :) Однако, если importData() никогда не завершается, проблема гораздо серьезнее. Использование второй задачи также является идеей. – davidxxx

+0

Я обязательно попробую. Поскольку данные для импорта могут быть огромными, в первый раз, когда я думаю, что я буду разделять их на куски и импортировать их кусок за раз каждый раз, когда запускается запланированное задание. Но если я запустил его как поток, как я могу его убить, если я нахожу, что он превышает срок, так как у меня нет ссылки на него (в идее использовать вторую задачу для определения застрявшего состояния)? Извините, может быть, я вернусь к исходному вопросу. – frankieta

0

Во-первых, обязательно. Существует много методов, которые могут напомнить вам, заблокирован ли процесс, например журнал/сообщение/письмо, вставляемое в ваш код.

Во-вторых, это решение, если вы хотите его блокировать или нет. Если вы не намерены блокировать, новый поток или тайм-аут могут быть вам по выбору.

+0

Да, блок не является моим намерением. Ограниченный интервал времени (5 минут) заключается в том, что пользователи хотят увидеть результат импорта в полуреальном времени. – frankieta

Смежные вопросы