Как получить доступ к объекту 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?
}
}
Ответы
Ответ 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.