简体   繁体   English

如何通过线程访问可运行对象?

[英]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. 我有一个实现runnable的类,还有一个List,用于存储用该类的不同对象实例化的线程。 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. 我在java.lang.Thread文档中看不到任何方法。

My best answer, then, is that you probably should be using List<Runnable> instead of (or in addition to) List<Thread> . 那么,我最好的答案是您可能应该使用List<Runnable>而不是List<Thread> (或除了List<Thread>之外)。 Or perhaps you want some sort of map structure so that you can access the Runnable from the Thread. 或者,也许您想要某种映射结构,以便可以从线程访问Runnable。 (For example, java.util.HashMap<java.lang.Thread, java.lang.Runnable> ) (例如, 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() 注意:如果您的任务抛出异常,则当您调用get()时,Future将保留此异常并引发包装异常。

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 顺便说一句,在实际情况下,您需要使用CallableFutureTask

If you want to return the value of an asynchronous calculation, look at Callable and FutureTask: 如果要返回异步计算的值,请查看Callable和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): 我认为通常您可以/应该避免这样做,但是如果您确实需要这样做,则不应该像MatrixFrog的建议工作(未经测试)那样:

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 . 但是,执行此类操作的现代方法(不太容易出错)是使用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. 您可以继承Thread的子类,并添加所需的方法。 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. 由于一些令人讨厌的Thread实现细节,您必须保留自己的目标Runnable副本,并覆盖用于创建Thread的所有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. 而且您的runnable具有start()函数,该函数将启动并自行启动本地线程并调用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();
    }

}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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