5

As far as I can understand from the java.lang.Thread docs, and from other questions posted here on stackoverflow, like "How to access a Runnable object by Thread?" and "Get current instance of Runnable" it's not possible to get a reference of the Runnable object embedded in a Thread.

A scenario where having this possibility would be useful is when implementing a method, whose signature can't be modified because we are overriding a method defined in another class or interface, and different operations are required to be performed depending on the type of Runnable embedded in the current Thread.

If we had for example a method called getRunnable in the Thread class we could do something like this:

if (Thread.currentThread().getRunnable() instanceof Type1) {
  // do something...
} else {
  // do something else...
}

This could be useful also in situations when we want to ensure the operations contained in a method are executed only by certain threads and not by others.

So I was wondering, is there a specific reason why the Java developers decided to not allow to get the Runnable instance from a Thread, or is it be a missing feature worth to be notified? If you think there is no reason behind that choice but it's not worth to notify it as missing feature, what strategy would you use in the scenario described above?

Community
  • 1
  • 1
Marco Lackovic
  • 6,077
  • 7
  • 55
  • 56

3 Answers3

9

So I was wondering, is there a specific reason why the Java developers decided to not allow to get the Runnable instance from a Thread

It was probably just not a requirement. The Runnable itself should be able to identify its own class so the idea that it needs to get that information is strange. It could also be a protection so that other threads would not have access to the class being running in another thread.

If you need access to the current Runnable from other parts of your application then I'd recommend using a ThreadLocal<Runnable>. In your run() method you could set it and then retrieve it in your other classes. You'd need to put the ThreadLocal somewhere globally accessible however.

You could also process the current stack trace to figure out the enclosing Runnable class which is even more of a hack but it would work.

Gray
  • 115,027
  • 24
  • 293
  • 354
5

There are a couple approaches you could take to get around this:

Keep a mapping of your Runnables to the Threads that are executing them (either with a Map<Thread, Runnable> or with a ThreadLocal<Runnable>)
Use reflection to access the Runnable from the Thread:

private static final Field target;
static {
    Field f = null;
    try {
        f = Thread.class.getDeclaredField("target");
        f.setAccessible(true);
    } catch (NoSuchFieldException e) {
        // might happen in a different version of Java (works in Java 7)
        e.printStackTrace();
    }
    target = f;
}

public static Runnable getTarget(Thread t) {
    try {
        return (Runnable) target.get(t);
    } catch (IllegalAccessException e) {
        // shouldn't happen, we already made the field accessible when we created it
        e.printStackTrace();
        }
    return null;
}
Jeffrey
  • 44,417
  • 8
  • 90
  • 141
1

There is a indirect method may be it will help, You can get the stack trace.

StackTraceElement[] stackTraceElement = thread.getStackTrace();
for(StackTraceElement e :stackTraceElement){
   System.out.println("Trace "+e.getClassName());
}

Output :

Trace java.lang.Thread

Trace com.emc.multithreading.RunnableDemo

Trace java.lang.Thread

Amar T
  • 359
  • 1
  • 7