0

I've got a inner class in my class doing some asynchronous processing and setting value on parent class. Ex :

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

Now here is the problem from Runner class :

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

How do I get around this?

5
  • 3
    Since you don't appear to be doing anything concurrently, I would use just one thread. If you want to wait for asynchronous tasks I suggest you use an ExecutorService and Future.get(). Commented Sep 25, 2012 at 12:45
  • I don't think it will compile. Commented Sep 25, 2012 at 12:48
  • yes I was intending to wait for asynchronous task to complete and then to print out the result, but I don't know how Commented Sep 25, 2012 at 12:49
  • 1
    i would suggest reading one of the thousands of online tutorials on multi-threading in java. the oracle one is always a good place to start. google will find you many more... Commented Sep 25, 2012 at 12:54
  • FYI dude, I forgot to threadPool.shutdown(); the pool in my example. Just edited it. Commented Sep 26, 2012 at 17:27

5 Answers 5

2

Others have suggested similar ideas but I'd use a single thread pool with a Callable.

Your class that is doing the asynchronous processing should implement Callable which will return the computed value. In this example it returns a String but it could also return your own object with more information.

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

Your Runner class would then create a thread pool, fire off the asynchronous task in the background, and then later wait for it to finish. When you submit a Callable job to the thread-pool, you get a Future class back which can be used to wait for the asynchronous job to finish and to get its return value.

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);
    }
}
Sign up to request clarification or add additional context in comments.

1 Comment

I have a similar use case, trying to convert AsyncTasks to ExecutorService to return a List from a Room database. Another answer suggests using submit() on ExecutorService and get() on the Dao method (see stackoverflow.com/questions/52242933/room-database-query). Would appreciate your thoughts on that approach versus the approach using a Callable and a Future.
2

Evidently, you have to make getTestValueFromMyClass to wait for InnerClass execution. This can be done with some synchronization facility (Semaphore, CountdownLatch, BlockingQueue...). But most straightforward is to use java.util.concurrent.ScheduledThreadPoolExecutor instead of java.util.Timer. Its method schedule(Callable<V> callable, long delay, TimeUnit unit) returns Future, and Future.get() waits for and returns the computed value.

Comments

2

One very simple mechanism is to use a BlockingQueue to communicate between your threads. Here I am creating the queue in the thread class but it could just as easily be created in the caller and passed to the thread.

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

Comments

0

You could use a handler and post a message when processing is done!

2 Comments

thank you for your response, do you have example/link, something similar I don't really know what you're talking about
sorry, my suggestion was intended for Android developing.You don't need a thread for this. But if you insist in having a separate thread, then just call a method when you are ready with processing!
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"
   }
}

2 Comments

this returns string Asynchronously calculated result, but my program is still running, why doesn't it end ?
Because resultHandler.get() waits if necessary for the computation to complete, and then retrieves result (also there is version of get with timeout): docs.oracle.com/javase/1.5.0/docs/api/java/util/concurrent/…

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.