How to retrieve the return result of a routine from within a Thread?

3

I need to run a routine inside a Thread, and get the return of this method. My code is this way.

class Main {
    public static void main(String[] args) {
        String resultado = "";
        Thread t = new Thread() {
            @Override
            public void run(){
                //varios processamentos
                String strDeRetorno = "abcde";///
                //???? Como retornar esse valor ao final da execucao??
            }
        };
        //Como recuperar o valor retornado pelo método run da Thread??
        t.start();
    }
}

Note that it is not a case of declaring some kind of global variable and changing it, so there are no "global variables" in Java. I really want to get the return value from the routine when it is done.

    
asked by anonymous 03.07.2015 / 12:39

2 answers

6

This functionality is achieved through the use of thread pools, available in Java, from version 1.5 on Executors Framework

Instead of creating a Thread , you create a Pool with a Thread , and submit to it the tasks you want this Thread execute. For this your routine should implement a Callable<T> . This is a simple interface, which has a call method, the equivalent of run that you would implement in an ordinary Thread, but with a subtle and powerful difference: It allows you to return a value of a type. p>

V call() throws Exception;

Let's go to the code:

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

public class Main {
    public static void main(String[] args) throws Exception{
        String resultado = "";

        //Criando um pool de Threads com uma Thread, 
        //equivalente ao sua Thread
        ExecutorService executor = Executors.newSingleThreadExecutor();

        //ao inves de chamarmos o metodo Thread.start(), chamamos:
        //executor.submit -> o que já permitirá que você obtenha um envólucro para
        //o resultado
        Future<String> futureResult = executor.submit(new Callable<String>() {

            //Note como este não é um Runnable, e sim um Callable("primo" do Runnable)
            @Override
            public String call() throws Exception {
                String retorno = "";
                //processando
                //sua lógica
                // e assim por diante
                retorno = "abcde";
                return retorno;
            }
        });

        //Obtendo um resultado da execucão da Thread
        resultado = futureResult.get();

        System.out.println(resultado);

        //lembrar de chamar o shutodown no executor - para encerrar a
        //execucão
        executor.shutdown();
    }
}

At the moment you submit your routine, the ExecutorService.submit method will give you a Future

This Future object will give you access to the return value of this callable that was executed by your Thread. This will be done by calling the method Future.get()

Remember to call: executor.shutdown - this will terminate the Pool, which will prevent new tasks from being executed.

  

* Please also read the comments in the example code. They should help you understand what is happening.

    
06.07.2015 / 04:18
1

The variable is global, but can not be accessed by different threads at the same time. For this to happen, the global variable must be declared as volatile . To pass parameters from one thread to another, we use Observer and Observable Here's how: link
Here is an example implementation:

public class Observador implements Observer
{
    public static void main(String[] args) 
    {
        final Observador main = new Observador();
        final Thread thread = new Thread(new Observado(main));
        thread.start();
    }

    @Override
    public void update(Observable o, Object arg) 
    {
        if(arg != null){
            System.out.println(arg);
        }
    }

    public static class Observado extends Observable implements Runnable
    {
        /**
         * Recebe quem irá receber as notificações....
         * @param o
         */
        public Observado(final Observer o) 
        {
            addObserver(o);
        }
        @Override
        public void run() 
        {
            int pt = 0;
            while(pt != 5){
                final Random random  = new Random();
                // gera um numero aleatorio 
                final Integer num =  random.nextInt();
                setChanged();
                //envia ao observador 
                notifyObservers(num);
                pt++;
            }

        }
    }
}
    
03.07.2015 / 15:49