Domanda

Nel codice di seguito, sto cattura di un TimeoutException dopo 100 secondi come previsto. A questo punto mi aspetterei il codice per uscire dal principale e il programma per terminare ma mantiene la stampa alla console. Come faccio ad avere il compito di fermare l'esecuzione dopo il timeout?

private static final ExecutorService THREAD_POOL = Executors.newCachedThreadPool();

private static <T> T timedCall(Callable<T> c, long timeout, TimeUnit timeUnit) throws InterruptedException, ExecutionException, TimeoutException {
    FutureTask<T> task = new FutureTask<T>(c);
    THREAD_POOL.execute(task);
    return task.get(timeout, timeUnit);
}


public static void main(String[] args) {

    try {
        int returnCode = timedCall(new Callable<Integer>() {
            public Integer call() throws Exception {
                for (int i=0; i < 1000000; i++) {
                    System.out.println(new java.util.Date());
                    Thread.sleep(1000);
                }
                return 0;
            }
        }, 100, TimeUnit.SECONDS);
    } catch (Exception e) {
        e.printStackTrace();
        return;
    }


}
È stato utile?

Soluzione

È necessario annullare il vostro compito in timeout (e interrupt suo filo). Questo è ciò che il metodo è per cancel(true). :

private static final ExecutorService THREAD_POOL = Executors.newCachedThreadPool();

private static <T> T timedCall(FutureTask<T> task, long timeout, TimeUnit timeUnit) throws InterruptedException, ExecutionException, TimeoutException {
    THREAD_POOL.execute(task);
    return task.get(timeout, timeUnit);
}


public static void main(String[] args) {
        try {
            FutureTask<Integer> task = new FutureTask<Integer>(new Callable<Integer>() {
                public Integer call() throws Exception {
                        for (int i=0; i < 1000000; i++) {
                                if (Thread.interrupted()) return 1;
                                System.out.println(new java.util.Date());
                                Thread.sleep(1000);
                        }
                        return 0;
                }
            });
            int returnCode = timedCall(task, 100, TimeUnit.SECONDS);
        } catch (Exception e) {
                e.printStackTrace();
                task.cancel(true);
        }
        return;
}

Altri suggerimenti

Il mosto richiamabile per essere in grado di fermare rapidamente, in caso di necessità.

Il tuo codice:

public Integer call() throws Exception {
    for (int i=0; i < 1000000 && !task.cancelled(); i++) {
        System.out.println(new java.util.Date());
        Thread.sleep(1000); // throws InterruptedException when thread is interrupted
    }
    return 0;
}

è già in grado di farlo grazie a chiamare Thread.sleep(). Punto è che futureTask.cancel(true) interromperà altro thread, e il codice ha bisogno di reagire a questa interruzione. Thread.sleep() fa. Se non è stato utilizzato Thread.sleep() o altro codice interrompibile di blocco, si dovrebbe controllare Thread.currentThread().isInterrupted() da soli, e uscire il più presto possibile (per esempio lanciando new InterruptedException()) quando si trova che questo è vero.

È necessario chiamare futureTask.cancel(true); dal vostro gestore di eccezioni per annullare e interrompere il thread che esegue il compito.

Il mio consiglio è quello di conoscere il meccanismo di interruzione (questo è grande articolo: Trattare con InterruptedException ), e usarlo.

Una volta che hai preso la TimeoutException, è necessario chiamare il metodo cancel (vero) del vostro compito ...

o spegnere l'ExecutorService chiamando shutdownNow () ...

o uscire la VM chiamando System.exit (0)

a seconda delle esigenze

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