Как получить доступ к объекту Runnable по потоку? - PullRequest
21 голосов
/ 20 февраля 2010

Возможный дубликат: Need-Help-Returning-Object-In-Thread-Run-метод

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

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

Ответы [ 11 ]

12 голосов
/ 20 февраля 2010

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

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

10 голосов
/ 20 февраля 2010

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

ExecutorService executor = Executors.newSingleThreadedExecutor();

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

String result = future.get(); 
4 голосов
/ 20 февраля 2010

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

FutureTask<String> task = new FutureTask(new Callable<String>() {
   public String call() {
      return "world";
   }
});
new Thread(task).start();
String result = task.get();
4 голосов
/ 20 февраля 2010
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

2 голосов
/ 13 марта 2014

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

2 голосов
/ 21 июня 2012

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

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

1 голос
/ 08 ноября 2014

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

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

}
1 голос
/ 22 января 2013

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

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;
}
1 голос
/ 20 февраля 2010

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

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.

0 голосов
/ 29 апреля 2018

Я думаю, если вы можете, это изменить ситуацию. Тогда в этом случае хорошее решение - сохранить поток в вашем исполняемом классе. И ваш 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();
    }

}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...