Используете ли вы Таймер в режиме демона? Пожалуйста, ознакомьтесь с этой документацией, в которой говорится, что такое поток демона.
/**
* Creates a new timer whose associated thread may be specified to
* {@linkplain Thread#setDaemon run as a daemon}.
* A daemon thread is called for if the timer will be used to
* schedule repeating "maintenance activities", which must be
* performed as long as the application is running, but should not
* prolong the lifetime of the application.
*
* @param isDaemon true if the associated thread should run as a daemon.
*/
public Timer(boolean isDaemon) {
this("Timer-" + serialNumber(), isDaemon);
}
Если вы используете поток демона, приложение не будет ждать завершения этого потока, поэтому завершение любой ожидающей операции в этом потоке не гарантируется. Однако, если это не поток демона, приложение закроется только после того, как этот поток завершит свою последнюю операцию.
Что касается закрытия файловых дескрипторов, почему бы вам не сделать это в самом потоке таймера? Если это невозможно сделать, ловушки Shudown - идеальный способ сделать что-то во время закрытия приложения.
Таким образом, вы можете иметь общую блокировку, которая может быть получена таймером для каждого выполнения задачи, и та же самая блокировка может быть получена задачей закрытия для закрытия дескрипторов открытого файла.
Надеюсь, это проясняет ситуацию.