Acording to the docs of Thread.getId():
Returns the identifier of this Thread. The thread ID is a positive long number generated when this thread was created. The thread ID is unique and remains unchanged during its lifetime. When a thread is terminated, this thread ID may be reused. [emphasis added]
However, in what cases will a thread ID be reused? Looking at the source code for Thread.java, the method to get the next thread ID just increments a static long:
private static synchronized long nextThreadID() {
return ++threadSeqNumber;
}
I don't see how this code will re-use an old ID, unless by re-use they simply mean that eventually an incremented long will loop back to a previous value (but that does not make sense because the long will become negative before doing so - which breaks the docs).
Question in a nutshell: in what way are Thread IDs reused, and what causes them to be reused?
This is a good example of the difference between a program's contract and implementation. Thread.getId() is guaranteed by contract to be unique across all live threads, however the contract does not guarantee that such IDs may not be reused one a thread has terminated. This means that regardless of the current implementation you must program with the assumption that old thread IDs could be reused.
That the exact cases in which it might be reused are not documented is an example of unspecified behavior. While unspecified behavior can be problematic it's also a necessary tool for library and language developers to avoid over-specifying contracts that they didn't mean to abide by. In this case the contract is essentially avoiding committing to ensuring unique thread IDs for the lifetime of the process, which simplifies the effort that must be expended to create new threads.
Consider if the contract instead promised to never reuse thread IDs. The Java authors would need to implement some sort of additional mechanism to ensure that additional contract. This would come with a cost (time, memory, and/or cognitive overhead on the part of the authors) that, essentially, the authors decided wasn't worth their while.
In short, the answer to your question is "we don't know", and that's by design. Avoid writing code that assumes the thread IDs will be globally unique, or one day your code may break.
As an aside, it's interesting that the specification does guarentee the ID will be positive, yet Thread.nextThreadID() doesn't enforce that. It's probably simply not a practical concern (you'd have to spin up 2^61 threads to run into this issue, which would take 73 million years at one thread per milisecond :) ), but it's interesting that they avoid promising uniqueness but don't actually ensure non-negative values. You'd reach the negatives before you reach a duplicate ID with the current implementation.
JDK classes can have many different implementations. You looked at an implementation of Thread, and found that it would never reuse thread-IDs; but the Javadoc is merely saying that a thread's ID may be reused after it's terminated, that is, that a JDK implementation may reuse the thread-ID of a terminated thread.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With