Подтвердить что ты не робот

Как получить доступ к объекту Runnable по потоку?

Возможный дубликат: need-help-returning-object-in-thread-run-method

Здравствуйте. У меня есть класс, реализующий runnable, и у меня есть List, хранящий потоки, созданные экземплярами разных объектов этого класса. Как я могу получить доступ к свойствам базовых объектов, если объект потока работает? Вот пример:

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

Ответ 1

Я не вижу никакого способа сделать это в java.lang.Thread docs.

Мой лучший ответ заключается в том, что вы, вероятно, должны использовать List<Runnable> вместо (или в дополнение к) List<Thread>. Или, возможно, вам нужна структура map, чтобы вы могли получить доступ к Runnable из потока. (Например, java.util.HashMap<java.lang.Thread, java.lang.Runnable>)

Ответ 2

Библиотека concurrency поддерживает эту функцию. Примечание. Если ваша задача выбрасывает исключение, будущее будет удерживать это и бросать исключение обертывания, когда вы вызываете get()

ExecutorService executor = Executors.newSingleThreadedExecutor();

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

String result = future.get(); 

Ответ 3

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

Кстати, в реальном случае вам нужно использовать Callable и FutureTask

Ответ 4

Если вы хотите вернуть значение асинхронного вычисления, посмотрите на Callable и FutureTask:

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

Ответ 5

Я думаю, что в общем вы можете/должны избегать этого, но если вам действительно нужно это делать, не должно быть что-то вроде работы с предложением MatrixFrog (непроверено):

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

?

Ответ 6

Вот как вы могли бы реализовать это напрямую.

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

Однако, современный способ (менее подверженный ошибкам) ​​- это использовать классы concurrency более высокого уровня в java.util.concurrent.

Ответ 7

У меня была та же проблема. Вот мое решение:

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

Ответ 8

Если ваш поток содержит информацию о состоянии, запустите Runnable и просто продолжите Thread, переопределив метод выполнения.

Ответ 9

Чтобы дать конкретный пример решения Пола Кроули, я думаю, что это то, что он предлагает:

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

}

Ответ 10

Вы можете подклассировать Thread и добавить необходимый вам метод. Вам придется сохранить собственную копию целевого Runnable и переопределить все конструкторы Thread, которые вы используете для создания Thread, из-за некоторых досадных деталей реализации Thread.