The sequence would be this:
- Thread A calls
getInstance
. Thread A takes the lock for a while, time to check thatinstance
is not null, which it isn't at this point. - Thread LogThread completes it's execution,
isRunning
is set to false.instance
is set to false, but is still retained by Thread A - Thread A calls
start
on the instance.isRunning
is false, thereforestart
is called, hence the crash.
A quick fix would be to not set isRunning
to false, since there is never any good reason for that instance to be available for starting again. It should then be renamed isStarted
for consistency with what it does.
A proper solution would be to use a newSingleThreadExecutor
, as suggested by @Mani