java - studio - process and thread android




Valore di ritorno da Thread (6)

È possibile utilizzare un array di variabili finali locali. La variabile deve essere di tipo non primitivo, quindi è possibile utilizzare un array. È inoltre necessario sincronizzare i due thread, ad esempio utilizzando CountDownLatch :

public void test()
{   
    final CountDownLatch latch = new CountDownLatch(1);
    final int[] value = new int[1];
    Thread uiThread = new HandlerThread("UIHandler"){
        @Override
        public void run(){
            value[0] = 2;
            latch.countDown(); // Release await() in the test thread.
        }
    };
    uiThread.start();
    latch.await(); // Wait for countDown() in the UI thread. Or could uiThread.join();
    // value[0] holds 2 at this point.
}

Puoi anche usare un Executor e un Callable come questo:

public void test() throws InterruptedException, ExecutionException
{   
    ExecutorService executor = Executors.newSingleThreadExecutor();
    Callable<Integer> callable = new Callable<Integer>() {
        @Override
        public Integer call() {
            return 2;
        }
    };
    Future<Integer> future = executor.submit(callable);
    // future.get() returns 2 or raises an exception if the thread dies, so safer
    executor.shutdown();
}

Ho un metodo con un HandlerThread . Un valore viene modificato all'interno del Thread e vorrei restituirlo al metodo test() . C'è un modo per fare questo?

public void test()
{   
    Thread uiThread = new HandlerThread("UIHandler"){
        public synchronized void run(){
            int value; 
            value = 2; //To be returned to test()
        }
    };
    uiThread.start();
}

Che ne dici di questa soluzione?

Non usa la classe Thread, ma è concomitante, e in un certo senso fa esattamente quello che chiedi

ExecutorService pool = Executors.newFixedThreadPool(2); // creates a pool of threads for the Future to draw from

Future<Integer> value = pool.submit(new Callable<Integer>() {
    @Override
    public Integer call() {return 2;}
});

Ora tutto ciò che dici è value.get() ogni volta che devi prendere il tuo valore restituito, il thread viene avviato proprio nel momento in cui dai value un valore in modo da non dover mai dire threadName.start() su di esso.

What a Future is, è una promessa al programma, prometti al programma che otterrai il valore necessario nel prossimo futuro

Se chiami .get() su di esso prima che sia terminato, il thread che lo chiama semplicemente aspetta solo che sia fatto


Di solito lo faresti in questo modo

 public class Foo implements Runnable {
     private volatile int value;

     @Override
     public void run() {
        value = 2;
     }

     public int getValue() {
         return value;
     }
 }

Quindi puoi creare il thread e recuperare il valore (dato che il valore è stato impostato)

Foo foo = new Foo();
new Thread(foo).start();
// ... join through some method
int value = foo.getValue();

tl;dr un thread non può restituire un valore (almeno non senza un meccanismo di callback). Dovresti fare riferimento a una discussione come una classe ordinaria e chiedere il valore.



Se si desidera il valore del metodo di chiamata, è necessario attendere il termine del thread, il che rende l'uso dei thread un po 'inutile.

Per rispondere direttamente alla domanda, il valore può essere memorizzato in qualsiasi oggetto mutabile sia al metodo chiamante sia al thread hanno un riferimento. Si potrebbe usare this esterno, ma questo non sarà particolarmente utile se non per semplici esempi.

Una piccola nota sul codice nella domanda: Estendere la Thread solito è di scarsa qualità. In effetti, estendere inutilmente le classi è una cattiva idea. Ho notato che il metodo di run è sincronizzato per qualche motivo. Ora, dato che l'oggetto in questo caso è il Thread puoi interferire con qualunque Thread usi il suo lock per (nell'implementazione di riferimento, qualcosa da fare con join , IIRC).


Usare Future descritto nelle risposte precedenti fa il lavoro, ma un po 'meno significativamente come f.get (), blocca il thread fino a quando non ottiene il risultato, il che viola la concorrenza.

La soluzione migliore è utilizzare ListenableFuture di Guava. Un esempio :

    ListenableFuture<Void> future = MoreExecutors.listeningDecorator(Executors.newFixedThreadPool(1, new NamedThreadFactory).submit(new Callable<Void>()
    {
        @Override
        public Void call() throws Exception
        {
            someBackgroundTask();
        }
    });
    Futures.addCallback(future, new FutureCallback<Long>()
    {
        @Override
        public void onSuccess(Long result)
        {
            doSomething();
        }

        @Override
        public void onFailure(Throwable t)
        {

        }
    };




multithreading