Вот небольшой рассказ, который вы можете использовать в качестве указателя:
Я кодировал TailingInputStream на работе по той же причине. Он в основном использует File и обновляет его содержимое по требованию и проверяет его по внутреннему буферу, если он значительно изменился (метка памяти 4KB IIRC), а затем сделал то, что делает tail -f. Немного хакерский, да, но он работает отлично и не связывается с Threads или чем-то подобным - он по крайней мере совместим с версией 1.4.2.
Тем не менее, это было намного проще, чем ReverseInputStream, который шел от конца файла к началу и не умирал, если файл обновлялся на лету ...