How to access a Runnable object by Thread?

Viewed 49981

Possible duplicate: need-help-returning-object-in-thread-run-method

Hello. I have a class implementing runnable and I have a List, storing Threads instantiated with different objects of that class. How can I access properties of underlying objects given the thread object running them? Here is an example:

public class SO {
    public static class TestRunnable implements Runnable {
        public String foo = "hello";

        public void run() {
            foo = "world";
        }
    }

    public static void main(String[] args) {
        Thread t = new Thread(new TestRunnable());
        t.start();
        //How can I get the value of `foo` here?
    }
}
11 Answers

I don't see any way to do it in the java.lang.Thread docs.

My best answer, then, is that you probably should be using List<Runnable> instead of (or in addition to) List<Thread>. Or perhaps you want some sort of map structure so that you can access the Runnable from the Thread. (For example, java.util.HashMap<java.lang.Thread, java.lang.Runnable>)

The concurrency library supports this well. Note: If your task throws an Exception, the Future will hold this and throw a wrapping exception when you call get()

ExecutorService executor = Executors.newSingleThreadedExecutor();

Future<String> future = executor.submit(new Callable<String>() { 
   public String call() { 
      return "world"; 
   } 
}); 

String result = future.get(); 
TestRunnable r = new TestRunnable();
Thread t = new Thread(r);
t.start();
//there you need to wait until thread is finished, or just a simple Thread.sleep(1000); at this case
System.out.println(r.foo);

BTW, in real case you need to use Callable and FutureTask

If you want to return the value of an asynchronous calculation, look at Callable and FutureTask:

FutureTask<String> task = new FutureTask(new Callable<String>() {
   public String call() {
      return "world";
   }
});
new Thread(task).start();
String result = task.get();

This is how you could implement this directly.

public static void main(String[] args) {
    // Keep a reference to the runnable object for later ...
    TestRunnable r = new TestRunnable();
    Thread t = new Thread(r);
    t.start();
    // Wait until the child thread has finished
    t.join();
    // Pull the result out of the runnable.
    System.out.println(r.foo);
}

However, the modern (less error prone) way to do this kind of thing is to use the higher-level concurrency classes in java.util.concurrent.

I think, if you can, it is to revert the situation. Then in this case a good solution is to store the thread in your runnable class. And your runnable has a start() function that launch and start itself the local thread and call thread.start. Like this you can have a list of your threaded objects. Also you can have an accessor to get the thread.

public class Threaded extends other implements Runnable {
    Thread localThread;

    @Override
    public void run() {
        //...
    }

    public void start() {
        localThread = new Thread(this);
        localThread.start();
    }

}
Related