Get all threads that run with a specified Runnable
I have one Runnable that is used by more than one thread:
Runnable myRunnable = new MyWorker();
Thread one = new Thread(myRunnable);
Thread two = new Thread(myRunnable);
one.start();
two.start();
How can I get all threads that are created with myRunnable
?
(Of course the example is simplified. I create new threads with myRunnable
on several places in different classes.)
Use case (as requested): MyWorkerOfMyPage
is a delayed worker that is bound to a page. If the user leaves this page (e.g. by navigating to another page) all threads that belong 开发者_JAVA百科to MyWorkerOfMyPage
should be killed ungracefully as their result is not needed anymore.
As already said best way is to track this yourself. This forces you to get a clear understanding of what you are doing. A good thing if you work with threads ... hmmm ... a good thing in every case ;).
But if you realy want to detect the threads you can use reflection with the Thread class to get the required information. First make the method "getThreads" accessible to get all running Threads, then make the field "target" accessible to get the runnables of the Threads.
Heres an example program (but I would advise against the usage in a real application. You should now what threads you are starting, it might harm compability with future JDKs, might harm portability ...):
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;
}
}
The best way to do this is to track this yourself. Use a global singleton for instance that launches the threads and track which ones you started.
Although my first thoughts are along @Bengt's lines, perhaps you could use Class.isAssignableFrom if you had a list of runnables and you just want to know which ones use your interface.
http://download.oracle.com/javase/6/docs/api/java/lang/Class.html
In Java there is no simple way to find all the places a object is referenced, its something you have to maintain a collection of yourself.
If you want to know this staticly you can Find Usages in your ide.
If you want to know this dynamically you can have the Runnable add the Thread to a collection (and remove it when finished)
Generally speaking, the developer should only create Threads deliberately. i.e. the Developer should know when he/she is creating thread and what those threads will be doing. Its not something you should be trying to track at runtime if you have a good design.
精彩评论