Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/343.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 为什么';在线程中嵌入Runnable是不可能的吗?_Java_Multithreading_Concurrency_Runnable - Fatal编程技术网

Java 为什么';在线程中嵌入Runnable是不可能的吗?

Java 为什么';在线程中嵌入Runnable是不可能的吗?,java,multithreading,concurrency,runnable,Java,Multithreading,Concurrency,Runnable,据我从文档以及stackoverflow上发布的其他问题(如“”和“”)中了解,无法获取嵌入线程中的可运行对象的引用 具有这种可能性的一个场景是在实现一个方法时,该方法的签名无法修改,因为我们正在重写另一个类或接口中定义的方法,并且需要根据当前线程中嵌入的可运行的类型执行不同的操作 例如,如果我们在Thread类中有一个名为getRunnable的方法,我们可以这样做: if (Thread.currentThread().getRunnable() instanceof Type1) {

据我从文档以及stackoverflow上发布的其他问题(如“”和“”)中了解,无法获取嵌入
线程中的
可运行
对象的引用

具有这种可能性的一个场景是在实现一个方法时,该方法的签名无法修改,因为我们正在重写另一个类或接口中定义的方法,并且需要根据当前
线程中嵌入的
可运行的
类型执行不同的操作

例如,如果我们在
Thread
类中有一个名为
getRunnable
的方法,我们可以这样做:

if (Thread.currentThread().getRunnable() instanceof Type1) {
  // do something...
} else {
  // do something else...
}
当我们希望确保方法中包含的操作仅由某些线程而不是其他线程执行时,这也很有用

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

所以我想知道,Java开发人员决定不允许从线程获取可运行实例有什么具体原因吗

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

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


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

有几种方法可以解决此问题:

保持
Runnable
s到执行它们的
线程的映射(使用
Map
ThreadLocal

使用反射从
线程访问
可运行的

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;
}

有一个间接的方法可能会有帮助,你可以得到堆栈跟踪

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

跟踪java.lang.Thread

跟踪com.emc.multi-threading.RunnableDemo


Trace java.lang.Thread

使用
main
方法,主线程的“可运行”是什么?像您在示例中所做的那样,在
instanceof
的结果上进行分支几乎从来都不是一个好主意。我不打算提供这个答案,因为这会非常密集,但是嘿。您可以研究如何使用线程堆栈跟踪
Thread.currentThread().getStackTrace()
。我不知道原因,但是您也可以扩展Thread类,在子类中保留对Runnable对象的引用,并提供getter方法在需要时获取Runnable。不是所有
Thread
实例都有Runnable,不是吗?