Domanda

Ho il seguente codice Java:

final Future future = exeService.submit(
    new Runnable() {
        public void run() {
            myObject.doSomething();
        }
    }
);

future.get();

dove exeService è un'istanza di

java.util.concurrent.ExecutorService

Il problema è che myObject.doSomething() non ritorna mai e, quindi, future.get() Non ritorna mai.

Tuttavia, se sostituisco la chiamata a submit con una chiamata a execute come questo:

exeService.execute(
    new Runnable() {
        public void run() {
            myObject.doSomething();
        }
    }
);

la chiamata a myObject.doSomething() torna. Non so se è importante, ma doSomething() è un void metodo.

Perché è doSomething() finire quando si usa execute ma non quando si usa submit?

Inoltre, non ho bisogno di usare Future.get(); Sembrava essere il modo più naturale per farlo. (Mi imbatto anche nello stesso problema con CountdownLatch.) Il punto è che devo aspettare doSomething() Per finire prima di procedere e, per motivi complicati non andrò qui, devo lanciarlo su un thread separato. Se c'è un altro modo di farlo che funzioni, andrebbe bene.

È stato utile?

Soluzione

Come in Executor.execute () Javadoc:

Esegue il comando indicato in qualche momento in futuro. Il comando può eseguire in un nuovo thread, in un thread pool o nel thread chiamante, a discrezione dell'implementazione dell'esecutore.

Quindi, il metodo execute() Restituisce immediatamente lasciandoti senza opzione per interrogare lo stato dell'attività inviata.

D'altro canto ExecutoService.submit ():

Invia un'attività eseguibile per l'esecuzione e restituisce un futuro che rappresenta tale attività. Il metodo Get del futuro restituirà null al completamento con successo.

Il Future.get () tornerà solo Dopo una competizione di successo, così mai nel tuo caso.

Questo è ulteriormente notato in Future.get () documentazione:

Attende se necessario per il completamento del calcolo, quindi recupera il suo risultato.

Altri suggerimenti

Ho creato un SSCCE:

package com.stackoverflow.q2585971;

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

public class Test {

    public static void main(String args[]) throws Exception {
        ExecutorService executor = Executors.newCachedThreadPool();
        Future<?> future = executor.submit(
            new Runnable() {
                public void run() {
                    try {
                        Thread.sleep(1000);
                    } catch (InterruptedException e) {
                        System.out.println("Epic fail.");
                    }
                }
            }
        );

        System.out.println("Waiting for task to finish..");
        future.get();
        System.out.println("Task finished!");
        executor.shutdown();
    }

}

Funziona perfettamente bene. Prima stampe

Waiting for task to finish..

poi dopo un secondo vedi

Task finished!

Quindi, il tuo problema sta altrove. Duplicherò il mio commento sulla tua domanda qui:

La tua domanda è piuttosto confusa. Il primo costrutto dovrebbe funzionare. La confusione è in "ritorno". Non intendi solo "finire" o "eseguire"? La tua confusione sembra basarsi sul fatto che future.get() In realtà attende che il runnable sia finito e quindi bloccherà il thread e impedirà che esegui il residuo del codice dopo il future.get() linea.

I futures Java stanno bloccando! get(). This method blocks the current thread until a future instance completes its work, thus requiring the use of one thread more than the work that must be performed just to manage what happens when it is done

Controllare una stallo / i (e) doSomething.

Inizierei con la ricerca wait chiamate.

Se tu wait Per qualcosa, devi segnalare l'oggetto che stai aspettando dall'altro thread chiamando notify o notifyAll.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top