Reputation: 13
I've been using Thread#currentThread() in my Runnable#run() method to get a reference to the currently executing thread. Since the Runnable can be running for a while with multiple similar copies in parallel in an Executor, will it always return the same Thread object or can that change over the course of the the lifetime of the Runnable?
So basically, will I run into issues when I run this kind of Runnable for a while?
class MyRunnable implements Runnable {
@Override
public void run() {
Thread current = Thread.currentThread();
while(!current.isInterrupted()) {
try {
// some processing that can take a while...
} catch(InterruptedException e) {
// some cleanup
current.interrupt();
}
}
// goodbye
}
}
Upvotes: 1
Views: 1287
Reputation: 11130
Will the Thread.currentThread() method always return the same object troughout the Runnable's lifetime?
Yes, Thread.currentThread()
will return the same reference anytime you invoke it in a particular thread; however not throughout the Runnable's lifetime, but rather throughout the lifetime of the current thread.
Runnable
type exists independent from the Thread
, and you can use it without the latter. If you, for example, store the Runnable
instance reference in some variable, and you will pass the same instance to the Thread
, exiting the runner thread will not cause the deallocation of that instance of the Runnable
.
You should note, that once the thread kicks off with .start()
(after which, JVM internally calls .run()
), it is illegal to restart the thread after it completes execution. Generally, it is never legal to start the same thread more than once.
So, every time you call Thread.currentThread()
, you will obtain the reference to the currently executing thread object (reference to the thread, in which, this method is invoked).
Upvotes: -1
Reputation: 298439
You are asking the wrong question. As long as code is executed within the same thread, the expression Thread.currentThread()
will evaluate to the same object, which represents that thread.
But this has nothing to do with the “Runnable
’s lifetime”. The Runnable
, or more precisely the instance of the class implementing runnable, is an ordinary object that can be used independently of threads. Most notably, multiple threads may execute the run()
method of the same object:
class MyRunnable implements Runnable {
@Override
public void run() {
Thread current = Thread.currentThread();
System.out.println(current);
}
}
MyRunnable r = new MyRunnable();
new Thread(r).start();
new Thread(r).start();
new Thread(r).start();
Thread[Thread-0,5,main]
Thread[Thread-1,5,main]
Thread[Thread-2,5,main]
This, however doesn’t imply that it was wrong to assume to get the same Thread
instance for a particular execution.
To built on your example code:
class MyRunnable implements Runnable {
@Override
public void run() {
Thread current = Thread.currentThread();
while(!current.isInterrupted()) {
try {
Thread.sleep(100);
} catch (InterruptedException ex) {
current.interrupt();
}
}
System.out.println(current+" has been interrupted, exiting");
}
}
MyRunnable r = new MyRunnable();
Thread[] threads = { new Thread(r), new Thread(r), new Thread(r) };
for(Thread t: threads) t.start();
for(Thread t: threads) try {
Thread.sleep(400);
System.out.println("going to interrupt "+t);
t.interrupt();
t.join();
}
catch (InterruptedException ex) {
throw new AssertionError(ex);
}
will correctly print:
going to interrupt Thread[Thread-0,5,main]
Thread[Thread-0,5,main] has been interrupted, exiting
going to interrupt Thread[Thread-1,5,main]
Thread[Thread-1,5,main] has been interrupted, exiting
going to interrupt Thread[Thread-2,5,main]
Thread[Thread-2,5,main] has been interrupted, exiting
So Thread.currentThread()
will return the same object throughout the threads lifetime (when being called from that thread), not the runnable`s lifetime, but that’s precisely what you want. You could also use
class MyRunnable implements Runnable {
@Override
public void run() {
while(!Thread.currentThread().isInterrupted()) {
try {
Thread.sleep(100);
} catch (InterruptedException ex) {
Thread.currentThread().interrupt();
}
}
System.out.println(Thread.currentThread()+" has been interrupted, exiting");
}
}
to the same effect. But keep in mind that the first example works because the thread has been stored in a local variable. If you are going to store the thread into a field of the object, you have to ensure that the object is not used by multiple threads concurrently (as you always have to take care when using shared mutable state by multiple threads).
Upvotes: 5
Reputation: 20913
Each Thread
has its own ID and you can call method getId() to obtain it. Then you can determine if it is the same Thread
.
From the javadoc of the method 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.
Upvotes: 0