2

我有一个 Runnable 被多个线程使用:

Runnable myRunnable = new MyWorker();
Thread one = new Thread(myRunnable);
Thread two = new Thread(myRunnable);
one.start();
two.start();

如何获取使用创建的所有线程myRunnable

(当然这个例子是简化的。我myRunnable在不同类的几个地方创建了新线程。)

用例(根据要求):MyWorkerOfMyPage是绑定到页面的延迟工作人员。如果用户离开这个页面(例如通过导航到另一个页面),所有属于的线程都MyWorkerOfMyPage应该被粗暴地杀死,因为不再需要它们的结果。

4

4 回答 4

4

最好的方法是自己跟踪。例如,使用全局单例来启动线程并跟踪您启动了哪些线程。

于 2011-06-27T09:52:19.707 回答
4

如前所述,最好的方法是自己跟踪。这迫使您清楚地了解自己在做什么。如果你使用线程是一件好事......嗯......在任何情况下都是一件好事;)。

但是,如果您真的想检测线程,您可以使用 Thread 类的反射来获取所需的信息。首先使方法“getThreads”可访问以获取所有正在运行的线程,然后使字段“target”可访问以获取线程的可运行对象。

这是一个示例程序(但我建议不要在实际应用程序中使用。您现在应该启动什么线程,它可能会损害与未来 JDK 的兼容性,可能会损害可移植性......):

import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.List;

public class Main {
    public static void main(String[] args) throws Exception {
        Runnable myRunnable = new Runnable() {
            @Override
            public void run() {
                try {
                    System.out.println("Start: " + Thread.currentThread().getName());
                    Thread.sleep(100);
                } catch (InterruptedException e) {
                    throw new RuntimeException(e);
                }
            }
        };
        Thread one = new Thread(myRunnable);
        Thread two = new Thread(myRunnable);
        one.start();
        two.start();

        List<Thread> threads = getThreadsFor(myRunnable);
        for (Thread thread : threads)
            System.out.println("Found: " + thread.getName());
    }

    private static List<Thread> getThreadsFor(Runnable myRunnable) throws Exception {
        Method getThreads = Thread.class.getDeclaredMethod("getThreads");
        Field target = Thread.class.getDeclaredField("target");
        target.setAccessible(true);
        getThreads.setAccessible(true);
        Thread[] threads = (Thread[]) getThreads.invoke(null);
        List<Thread> result = new ArrayList<Thread>();
        for (Thread thread : threads) {
            Object runnable = target.get(thread);
            if (runnable == myRunnable)
                result.add(thread);
        }
        return result;
    }
}
于 2011-06-27T14:03:35.857 回答
1

虽然我的第一个想法是@Bengt 的思路,但如果您有一个可运行的列表并且您只想知道哪些使用您的界面,那么您可能可以使用 Class.isAssignableFrom。

http://download.oracle.com/javase/6/docs/api/java/lang/Class.html

于 2011-06-27T10:05:16.460 回答
0

在 Java 中,没有简单的方法可以找到引用对象的所有位置,您必须自己维护一个集合。

如果你想静态地知道这一点,你可以在你的 ide 中找到用法。

如果您想动态了解这一点,您可以让 Runnable 将线程添加到集合中(并在完成后将其删除)

一般来说,开发者应该只刻意创建线程。即开发人员应该知道他/她何时创建线程以及这些线程将做什么。如果你有一个好的设计,你不应该在运行时跟踪它。

于 2011-06-27T09:55:49.190 回答