У меня есть работа в Java-приложении, которое считывает данные из базы данных Oracle с использованием Spring JDBC через каждые 5 минут. Приложение Java работает на WebSphere Application Server. Он загружает записи со статусом "X", после загрузки записей он изменяет статус записей на "Y". Мы читаем 10 тыс. Записей за один раз и поставляем записи по 1 к каждому потоку в течение 10 потоков для определенной Обработки.
После обработки каждой записи состояние записи изменяется на "Z". Теперь, если что-то пойдет не так во время обработки записей, таких как ошибка outOfMemory, а WebSphere опускается, состояние записи остается "Y".
Поэтому, когда в следующий раз Сервер запустится, задание начнет чтение записей со статусом "X". Но записи, которые не обрабатываются статусом "Y", никогда не будут загружены. Так можно ли вызвать метод, пока WebSphere не работает? Внутри которой я могу написать фрагмент кода, чтобы статус необработанных записей был "X", чтобы они могли быть выбраны при следующем запуске сервера.
Если приложение столкнулось с OutOfMemoryError
на самом деле нет надежного способа убедиться, что какой-то код будет выполнен до его спуска (фактически, OutOfMemoryError
фактически не заставит процесс умереть сам по себе, но это не имеет значения - если вы "Из памяти вы не можете быть уверены, что в этом процессе вы сможете вообще что-либо сделать".
Что вам нужно сделать, так это избавиться от состояния "Y". Просто убедитесь, что задание, которое читает элементы, не может выполняться более одного раза (см. Ниже). Затем вы можете просто прочитать элементы, отправить их для обработки и просто установить состояние на "Z", когда вы закончите (желательно в той же транзакции, что и обработка каждого элемента).
Теперь вы не указываете, как ваша работа запускается каждые пять минут, поэтому я просто предполагаю, что для этого вы используете функциональность Spring scheduling. Если это так, задание никогда не будет срабатывать более одного раза, пока оно все еще работает. Это означает, что ваша работа должна отслеживать отправленные предметы и ждать их завершения до выхода. Это можно сделать, используя ExecutorCompletionService. Отправляйте каждую подзадачу (т.е. Кусок записей 1k) в тот же ExecutorCompletionService
и опрос для законченных задач, если осталось больше задач. Когда все подзадачи возвращены, вы можете спокойно выйти из родительского задания.
Другой способ сделать это (если состояние "Y" требуется по какой-то определенной причине) было бы проверять записи "Y" при запуске, например, в методе, аннотированном с @PostConstruct
Поскольку вы отметили вопрос с spring
, вы должны просто использовать одноэлементный компонент с destroy-method
метода destroy-method
: он будет уничтожен, когда контекст приложения будет закрыт, и это произойдет, когда приложение будет остановлено.
XML: <bean class="..." destroy-method="destroy"/>
JavaConfig:
@Bean(destroy-method = "destroy")
public class ... {
public void destroy() {
// do you cleanup
}
}
ExecutorService
; постоянное создание новых потоков в системе - верный способ в конечном итоге исчерпать системные ресурсы.