web-dev-qa-db-ja.com

スレッドでRunnableオブジェクトにアクセスする方法は?

重複の可能性: need-help-returning-object-in-thread-run-method

こんにちは。 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?
    }
}
25
Fluffy

Java.lang.Thread ドキュメント。

私の最良の答えは、あなたはおそらくList<Runnable>の代わりに(またはそれに加えて)List<Thread>。または、スレッドからRunnableにアクセスできるように、何らかの map 構造が必要な場合もあります。 (例えば、 Java.util.HashMap<Java.lang.Thread, Java.lang.Runnable>

13
Platinum Azure

並行処理ライブラリはこれをうまくサポートしています。注:タスクが例外をスローする場合、Futureはこれを保持し、get()を呼び出したときにラッピング例外をスローします

ExecutorService executor = Executors.newSingleThreadedExecutor();

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

String result = future.get(); 
10
Peter Lawrey
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を使う必要があります

5
Igor Artamonov

非同期計算の値を返したい場合は、CallableとFutureTaskを見てください:

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

私は一般にこれを行うことができる/すべきではないと思いますが、本当に必要な場合は、MatrixFrogの提案作業(テストされていない)のようなものであってはなりません。

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

2
Chinasaur

スレッドに状態情報がある場合は、Runnableを忘れて単純にThreadを拡張し、runメソッドをオーバーライドします。

2
gerardw

私も同じ問題を抱えていました。これが私の解決策です:

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
user1870213

これは、これを直接実装する方法です。

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で高レベルの同時実行クラスを使用することです。

1
Stephen C

ポール・クローリーの解決策の具体例を示すために、私はこれが彼が示唆していることだと思います:

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
Janus Varmarken

できれば状況を元に戻すことだと思います。次に、この場合の適切な解決策は、スレッドを実行可能なクラスに格納することです。そして、ランナブルには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();
    }

}
0
user9717730

スレッドをサブクラス化し、必要なメソッドを追加できます。 Threadのいくつかの煩わしい実装の詳細のため、ターゲットRunnableの独自のコピーを保持し、Threadの作成に使用するすべてのThreadコンストラクターをオーバーライドする必要があります。

0
Paul Crowley