Подтвердить что ты не робот

Что следует учитывать при написании java-программы, которая должна запускаться "навсегда",

Мне нужно написать программу, которая, как считается, запускается "навсегда", что означает, что она не будет прерываться регулярно. До сих пор я всегда писал программы, которые запускались бы и заканчивались в конце дня. Программа должна выполнить несколько синхронизаций, сделать паузу в течение n минут и повторить синхронизацию.

AFAIK не должно быть проблем с моей текущей реализацией, и теоретически он должен работать нормально, но мне не хватает реального опыта.

Так есть ли какие-либо "шаблоны" или лучшие практики для написания очень надежных и ресурсоэффективных java-программ, которые имеют очень длительное время? Какие могут быть проблемы после, например, месяца/года выполнения?

Некоторая предыстория:

  • Java: 1.7, но скомпилировано до 1.5
  • ОС: Windows (точная версия еще не определена)

Заранее спасибо

4b9b3361

Ответ 1

Просто свалка мозга из всех вещей, которые мне приходилось иметь в виду при написании такого приложения.

Избегать утечек памяти

У меня было приложение, которое запускается один раз в середине дня, каждый день, и в том, что у меня есть FileWriter. Я не закрывал это должным образом, и затем мы начали задаваться вопросом, почему наша виртуальная машина собирается расплавиться после нескольких недель. Утечки памяти могут прийти в форме anyhing действительно, причем одним из наиболее распространенных примеров является то, что вы не de-reference объект соответствующим образом. Например, использование поля класса как метода временного хранения. Часто класс сохраняется, так же как и ссылка. Это оставляет вас с объектами, сидящими в памяти и ничего не делая.

Использовать правильный тип планировщика

Я использовал java Timer в этом приложении, а позже я узнал, что лучше использовать ScheduledThreadPoolExecutor в другом приложении было изменение системных часов. Поэтому, если вы планируете полностью поддерживать Java, я настоятельно рекомендую использовать это по таймеру по всем причинам, описанным в этом вопросе.

Помните об использовании памяти и вашей среды

Если ваше приложение загружает большие объемы данных каждый день, и у вас есть другие приложения, работающие на одном сервере, вы можете быть осторожны в отношении времени. Например, скажем, в середине дня три приложения запускают запланированную операцию, я бы сказал, что запуск в любой другой момент, вероятно, будет разумным шагом. Помните об окружающей среде, в которой вы выполняете свой код.

Обработка ошибок

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

Сделать его настраиваемым

Опять же, если он должен работать в разных точках дня, вам не нужно будет тянуть вещь в течение нескольких часов, чтобы выработать некоторые незначительные изменения в вашем коде. Вместо этого переместите его в файл свойств Java или в конфигурацию XML (или, действительно, что угодно). Преимущество этого заключается в том, что вы можете обновить свою программу и запустить ее, прежде чем кто-нибудь действительно заметит разницу.

Бойтесь ключевого слова static

Этот плохой мальчик сделает объекты упорными, даже когда вы уничтожите их родительскую ссылку. Это мама всех утечек памяти, если вы не будете осторожны с ней. Это отлично подходит для констант, и все, что вам известно, не нуждается в изменении и должно существовать в рамках проекта, чтобы работать хорошо, но если вы используете его для случайных значений внутри проекта, вы быстро задаетесь вопросом, почему ваш приложение рушится каждые несколько часов, а не syncing.

Подтверждает @X86, чтобы напомнить мне об этом.

Ответ 2

Утечки памяти, вероятно, будут самой большой проблемой. Убедитесь, что после итерации вашей логики нет долгосрочных ссылок. Даже относительно небольшой объект, на который ссылаются навсегда, в конечном итоге исчерпает память (и хуже того, будет сложнее обнаружить во время тестирования, если скорость роста составляет 1 ГБ/месяц). Один из подходов, который может помочь, заключается в использовании функции моментальных снимков профилировщиков: сделайте снимок во время паузы, пусть синхронизация выполняется несколько раз и выполняется другой снимок. Сравнивая их, следует показать дельта между синхронизациями, которые, надеюсь, будут равны нулю.

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

Последнее, что я упомянул, это обработка исключений. Для непродолжительных процессов это достаточно часто, чтобы просто позволить процессу умереть, когда встречается исключение, поэтому проблему можно решить, и приложение снова запустится. При длительном процессе вы, вероятно, должны быть более защитными, чем это. Рассмотрите возможность запуска частей вашей программы в потоках, которые можно перезапустить * если/когда они не работают. Вам может понадобиться модуль типа супервизора, который проверяет, что все остальное все еще болит и перезагружает его, если нет. Если это уместно для вашей структуры, это гораздо проще, чем для Java-исполнителей. И если это вообще возможно, вы можете захотеть иметь крючки (возможно, выставленные над JMX/MBeans), которые позволят вам немного изменить поведение, чтобы можно было повлиять на кратковременный хак/обходной путь без необходимости переноса процесса. Хотя для этого требуется довольно много предусмотрительности, чтобы точно предсказать, что произойдет через несколько месяцев...

* или, скорее, задание можно перезапустить в другом потоке