From the Thread API, here is a complete list:
- If the run() method returns.
- If an exception is thrown that propagates beyond the run method.
- If it is a daemon thread and all non-daemon threads have ‘died’
- If the exit method of class Runtime has been called (even at another thread).