如何通过线程访问Runnable对象?

可能重复: need-help-returning-object-in-thread-run-method

你好。 我有一个实现runnable的类,我有一个List,存储用该类的不同对象实例化的Threads。 在线程对象运行它们的情况下,如何访问底层对象的属性? 这是一个例子:

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

我在java.lang.Thread文档中看不到任何方法。

那么,我最好的答案是你可能应该使用List而不是(或除了) List 。 或者您可能想要某种地图结构,以便可以从Thread访问Runnable。 (例如, java.util.HashMap

并发库很好地支持了这一点。 注意:如果您的任务抛出exception,则Future将保持此状态并在调用get()时抛出包装exception

 ExecutorService executor = Executors.newSingleThreadedExecutor(); Future future = executor.submit(new Callable() { 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); 

顺便说一句,在实际情况下,您需要使用CallableFutureTask

如果要返回异步计算的值,请查看Callable和FutureTask:

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

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

我认为一般来说你可以/应该避免这样做,但是如果你真的需要这样做,那就不应该像MatrixFrog的建议那样(未经测试):

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

这是你如何直接实现这一点。

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

但是,现代(不易出错)的方法是在java.util.concurrent使用更高级别的并发类。

我有同样的问题。 这是我的解决方案:

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

为了给出保罗克劳利解决方案的具体例子,我认为这是他的建议:

 public class BackgroundJob extends Thread { private final JOB mJob; public BackgroundJob(JOB job) { super(job); mJob = job; } public JOB getJob() { return mJob; } } 

您可以inheritanceThread,并添加您需要的方法。 您必须保留自己的目标Runnable副本并覆盖用于创建Thread的所有Thread构造函数,因为Thread的一些恼人的实现细节。

我想,如果可以的话,就是要恢复局面。 那么在这种情况下,一个好的解决方案是将线程存储在runnable类中。 并且你的runnable有一个start()函数,它启动并启动本地线程并调用thread.start。 像这样,您可以拥有一个线程对象列表。 你也可以有一个访问器来获取线程。

 public class Threaded extends other implements Runnable { Thread localThread; @Override public void run() { //... } public void start() { localThread = new Thread(this); localThread.start(); } }