4

据我从java.lang.Thread文档以及stackoverflow上发布的其他问题(例如“如何通过线程访问Runnable对象? ”和“获取Runnable的当前实例”)了解,无法获得Runnable嵌入对象的引用在一个Thread

具有这种可能性的一个场景是在实现一个方法时,它的签名不能被修改,因为我们正在覆盖另一个类或接口中定义的方法,并且需要根据Runnable嵌入的类型执行不同的操作当前Thread.

getRunnable例如,如果我们在类中调用了一个方法,Thread我们可以这样做:

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

这在我们希望确保方法中包含的操作仅由某些线程执行而不由其他线程执行的情况下也很有用。

所以我想知道,Java 开发人员决定不允许Runnable从 a 获取实例是否有特定原因Thread,或者它是否是值得通知的缺失功能?如果您认为该选择没有理由,但不值得将其通知为缺少功能,那么您会在上述场景中使用什么策略?

4

3 回答 3

9

所以我想知道,Java 开发人员决定不允许从 Thread 获取 Runnable 实例是否有特定原因

这可能不是一个要求。它Runnable本身应该能够识别自己的类,因此它需要获取该信息的想法很奇怪。它也可以是一种保护,以便其他线程无法访问在另一个线程中运行的类。

如果您需要从应用程序的其他部分访问电流Runnable,那么我建议您使用ThreadLocal<Runnable>. 在您的run()方法中,您可以设置它,然后在其他类中检索它。但是,您需要将其ThreadLocal放在全局可访问的地方。

您还可以处理当前堆栈跟踪以找出封闭Runnable类,这更像是一种黑客攻击,但它会起作用。

于 2012-05-04T17:02:00.543 回答
4

您可以采取几种方法来解决此问题:

保留您Runnable的 s 到Thread正在执行它们的 s 的映射(使用 aMap<Thread, Runnable>或使用 a ThreadLocal<Runnable>
使用反射Runnable从以下访问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;
}
于 2012-05-04T17:09:17.157 回答
0

有一种间接方法可能会有所帮助,您可以获得堆栈跟踪。

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

输出 :

跟踪 java.lang.Thread

跟踪 com.emc.multithreading.RunnableDemo

跟踪 java.lang.Thread

于 2017-05-10T09:47:27.253 回答