views:

184

answers:

4

Let's say we have this simple example:

public Example extends Thread{

    String temp;    

    public Example(){
    }

    @Override
    public void run(){
    .
    .
    .
    .
    temp = "a_value";
    }

    public static void main(String[] args) {

        Example th = new Example();
        th.start();
    }

}

How can the Thread after finishing its job return me the String temp?

+2  A: 

You can achieve this by the Observer pattern. on finishing the thread notifies all listeners that it's finished and they can retrieve the value (through a getter). Or it can even already send the computed value.

Or you can use a task, see FutureTask, a runnable ( indeed as stated below a Callable ) that returns a result and can throw exceptions.

Redlab
+7  A: 

Look at Future interface javadoc. It has sample usage showing you how to do this.

Paul McKenzie
+9  A: 

Make use of the (relatively) new Callable<T> instead of Runnable.

Here is a (simple) example:

import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;


public class Main
{
    public static void main(final String[] argv)
    {
        final ExecutorService service;
        final Future<String>  task;

        service = Executors.newFixedThreadPool(1);        
        task    = service.submit(new Foo());

        try 
        {
            final String str;

            // waits the 10 seconds for the Callable.call to finish.
            str = task.get();
            System.out.println(str);
        }
        catch(final InterruptedException ex)
        {
            ex.printStackTrace();
        }
        catch(final ExecutionException ex)
        {
            ex.printStackTrace();
        }

        service.shutdownNow();
    }
}

class Foo
    implements Callable<String>
{
    public String call()
    {
        try
        {
            // sleep for 10 seconds
            Thread.sleep(10 * 1000);
        }
        catch(final InterruptedException ex)
        {
            ex.printStackTrace();
        }

        return ("Hello, World!");
    }
}
TofuBeer
"(relatively) new" Relative to what? It was introduced in a version that has now completed its end of service life period.
Tom Hawtin - tackline
Relative to releases... 1.6 is current, it was released in 1.5. Compare that with Thread which was there in 1.0... lot's of books that students learn from don't have Callable in it.
TofuBeer
A: 

If you don't want to swap the solution to use Callable objects then you can use also queues and return the result from the threads that way. I re-wrote your example like this:

import java.util.PriorityQueue;
import java.util.Queue;

public class GetResultFromThread {
  public static void main(String[] args) throws Exception {
    Queue<String> queue = new PriorityQueue<String>();
    int expectedResults = 2;
    for (int i = 0; i < expectedResults; i++) {
        new Example(queue).start();
    }

    int receivedResults = 0;
    while (receivedResults < expectedResults) {
        if (!queue.isEmpty()) {
            System.out.println(queue.poll());
            receivedResults++;
        }
        Thread.sleep(1000);
    }
  }
}

class Example extends Thread {
  private final Queue<String> results;

  public Example(Queue<String> results) {
    this.results = results;
  }

  @Override
  public void run() {
    results.add("result from thread");
  }
}

Note that you shall think of synchronization and concurrency!

Martin