Вариант первого решения, которое вы предлагаете, достаточно распространен в Un * x для процессов: сохраните файл pid запущенного процесса в файле при запуске. При повторном запуске программы вы можете проверить, существует ли этот файл (и даже если процесс с этим pid запущен).
С Java вы могли бы адаптировать эту идею, используя Threadid, определенный в ThreadMXBean. Но любой файл подойдет. Файл, который содержит ключ, как вы предлагаете, кажется достаточно хорошим способом. Вы также можете поместить в него некоторую полезную информацию, такую как время последнего выполнения. Если это все еще там при запуске, программа не остановилась чисто.
Он также может стать чем-то вроде файла журнала запуска, который отслеживает события программы, включая запуск и чистые остановки, и, возможно, блокировки.