0

私のクラスには、非同期処理を行い、親クラスに値を設定する内部クラスがあります。元 :

class Myclass{
   String test;

   public getTestValueFromMyClass(){
      //this starts asynchronous processing on my inner class
   }

   //inner class
   class InnerClass extends TimerTask{
      //doing something asynchronously, when this process is done
      test = "somevalue";
   }
}

ここにランナークラスの問題があります:

class Runner{
    public static void main(String[] args){
       Myclass instance = new Myclass();

       //This is always null because runner class doesn't wait for Inner class to
       //complete asynchronous processing and to set test value
       System.out.println(instance.getTestValueFromMyClass());
    }
}

どうすればこれを回避できますか?

4

5 に答える 5

2

非常に単純なメカニズムの 1 つは、 を使用しBlockingQueueてスレッド間で通信することです。ここでは、スレッド クラスでキューを作成していますが、呼び出し元で簡単に作成してスレッドに渡すこともできます。

public class Runner {
  static class MyClass implements Runnable {
    // Thread will post to this queue when it completes.
    BlockingQueue q = new ArrayBlockingQueue(1);

    // Call to wait for the post.
    public void waitForFinish() throws InterruptedException {
      // Just take! This will wait until something gets posted.
      q.take();
    }

    @Override
    public void run() {
      try {
        // Just wait ten seconds.
        Thread.sleep(10000);
      } catch (InterruptedException ex) {
        // Just exit when interrupted.
      } finally {
        try {
          // Signal finished.
          q.put("Done");
        } catch (InterruptedException ex) {
          // Just exit when interrupted.
        }
      }
    }
  }

  public static void main(String[] args) throws InterruptedException {
    // Make my instance.
    MyClass instance = new MyClass();
    // Fire it off.
    new Thread(instance).start();
    // Wait for it to finish.
    instance.waitForFinish();
    // All done.
    System.out.println("Finished");
  }
}
于 2012-09-25T13:07:19.133 に答える
2

明らかに、実行getTestValueFromMyClassを待つ必要がありますInnerClass。これは、いくつかの同期機能 (Semaphore、CountdownLatch、BlockingQueue など) を使用して実行できます。しかし、最も簡単なのはjava.util.concurrent.ScheduledThreadPoolExecutorの代わりに使用することですjava.util.Timer。そのメソッドschedule(Callable<V> callable, long delay, TimeUnit unit)は FutureFuture.get()を返し、計算された値を待って返します。

于 2012-09-25T12:54:43.847 に答える
2

他の人も同様のアイデアを提案していますが、私は単一のスレッド プールとCallable.

非同期処理を行っているクラスはCallable、計算された値を返す実装を実装する必要があります。この例では を返しますがString、より多くの情報を含む独自のオブジェクトを返すこともできます。

public class MyClass implements Callable<String> {
   public String call() {
      //doing something asynchronously, when this process is done
      return "somevalue";
   }
}

次にRunner、クラスはスレッド プールを作成し、バックグラウンドで非同期タスクを起動して、後で完了するのを待ちます。Callableジョブをスレッドプールに送信するFutureと、非同期ジョブが終了するのを待って戻り値を取得するために使用できるクラスが返されます。

public class Runner{
    public static void main(String[] args) {
       // you can use newFixedThreadPool(...) if you need to submit multiple
       ExecutorService threadPool = Executors.newSingleThreadExecutor();
       // you could store this future in a collection if you have multiple
       Future<String> future = threadPool.submit(new MyClass());
       // after submitting the final job, we _must_ shutdown the pool
       threadPool.shutdown();

       // do other stuff in the "foreground" while MyClass runs in the background

       // wait for the background task to complete and gets its return value
       // this can throw an exception if the call() method threw
       String value = future.get();
       System.out.println(value);
    }
}
于 2012-09-25T19:44:56.930 に答える
0

ハンドラーを使用して、処理が完了したらメッセージを投稿できます。

于 2012-09-25T12:44:05.107 に答える
0
class Myclass{
   // pre initialize thread pool
   private static ExecutorService executor = Executors.newFixedThreadPool( 5 );

   private String test;

   public String getTestValueFromMyClass() throws Exception {
      // start asynchronous calculations
      Future<String> resultHandler = 
           executor.submit( new Callable<String>() {
                    @Override
                    public String call() throws Exception {
                        return "Asynchronously calculated result";
                    }
                } );
      // do something in current thread
      // ...
      // wait until asynchronous task ends, get result 
      // and assign it to instance variable
      this.test = resultHandler.get();

      return test; // returns string "Asynchronously calculated result"
   }
}
于 2012-09-25T12:54:35.000 に答える