简体   繁体   中英

How to access a Runnable object by Thread?

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

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();

I think in general you can/should avoid doing this, but if you really need to do it shouldn't something like MatrixFrog's suggestion work (untested):

class RunnableReferencingThread extends Thread {
    public final Runnable runnable;
    public RunnableReferencingThread(Runnable r) {
        super(r);
        this.runnable = r;
    }
}

?

如果您的线程具有状态信息,请忘记Runnable并简单地扩展Thread,从而覆盖run方法。

I had the same problem. Here is my solution:

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

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

public static void main(String[] args) {
    TestRunnable runobject = new TestRunnable();
    Thread t = new Thread(runobject);
    runobject.foo;  //The variable from runnable. hello;
    t.start();
    runobject.foo;  //The variable from runnable. world;
}

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 .

To give a concrete example of Paul Crowley's solution, I think this is what he suggests:

public class BackgroundJob<JOB extends Runnable> extends Thread {

    private final JOB mJob;

    public BackgroundJob(JOB job) {
        super(job);
        mJob = job;
    }

    public JOB getJob() {
        return mJob;
    }

}

You could subclass Thread, and add the method you need. You'll have to keep your own copy of the target Runnable and override all the Thread constructors you use to create the Thread, because of some annoying implementation details of Thread.

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

}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM