2016-07-19 5 views
0

Wenn ich Futures bin mit wieVerwendung von shutdownNow in Concurrent Rahmen

List<Future<String>> results = executorService.invokeAll(tasks); 

oder

Future<String> res = executorService.submit(new SingleWorker()); 
System.out.println(res.get()); 

das System wartet auf die Aufgaben ausführen zu.

Auch wenn ich hatte executorService.shutdownNow(); nach den Anweisungen oben erwähnt, ich verstehe wirklich nicht, wenn das System mit Nachdruck der bestehenden Threads beenden, wie da in der Dokumentation erwähnt, das System nie erreicht die Linie , bis die Aufgaben abgeschlossen sind und eine Zukunft wird zurückgegeben. Fehle ich etwas? Gibt es ein anderes Testfall-Szenario, um es zu testen?

Will shutdownNow Arbeit nur mit Runnable das heißt, wenn wir sagen executorService.submit(new MyRunnable())?

EDIT:

ich einige verschiedene Dinge ausprobiert und fand heraus, dass

a) shutdownNow nicht mit invokeAll funktioniert.

b) shutdownNow falls vorhanden nach Future.get dann die Anweisung shutdownNow blockiert bisFuture aufgelöst wird (bei Callable).

c) shutdownNow funktioniert perfekt mit Runnable.

Es folgt der Code-Test geschrieben:

class SingleRunnableWorker implements Runnable { 

    @Override 
    public void run() { 
     System.out.println("SingleRunnableWorker Running.."); 
     try { 
      Thread.sleep(10000); 
      System.out.println("SingleRunnableWorker Running after sleep.."); 
     } catch (InterruptedException e) { 
      e.printStackTrace(); 
     } 
    } 

} 

class SingleCallableWorker implements Callable<String> { 

    @Override 
    public String call() throws Exception { 
     System.out.println("SingleCallableWorker Calling.."); 
     Thread.sleep(10000); 
     System.out.println("SingleCallableWorker Calling after sleep.."); 
     return "SingleCallableWorker Calling done"; 
    } 

} 

und ich bin es zu testen, wie folgt:

ExecutorService executorService = Executors.newFixedThreadPool(4); 
/*List<Future<String>> results = */executorService.invokeAll(tasks);//blocks by default 

Future<String> res = executorService.submit(new SingleCallableWorker()); 
//System.out.println(res.get()); //blocks if uncommented 

executorService.submit(new SingleRunnableWorker()); 

executorService.shutdownNow(); 

, wo Aufgaben sind alle Callables.

Bottomline ist invokeAll und Future.get sind blockierende Operationen. Kann jemand bitte bestätigen?

+2

'shutdownNow' wird versuchen, die Threads zu stoppen, die die Arbeit ausführen, die Sie dem entsprechenden' ExecutorService' übergeben. Vermutlich gibt es separate Threads, die 'Future # get()' machen. –

+1

"gewaltsam beenden?" nicht wirklich, lesen Sie das Dokument: "Es gibt keine Garantien über Best-Effort-Versuche, die Ausführung aktiv ausgeführter Aufgaben zu stoppen. Zum Beispiel werden typische Implementierungen über Thread.interrupt() abgebrochen, so dass jede Aufgabe, die nicht auf Interrupts reagiert, niemals beendet wird . " –

Antwort

1

Sowohl Runnbale als auch Callable, die Sie an ThreadPoolExecutor gesendet haben, werden als java.util.concrrent.FutureTask verpackt und ausgeführt.

In diesem Fall sowohl in SingleRunnableWorker und SingleCallableWorker, wenn Aufgabe durch Thread.sleep(10000) blockiert wird, executorService.shutdownNow() verursacht InterruptedException sofort geworfen werden.

Aber

  • InterruptedException in SingleRunnableWorker.run() geworfen ist gefangen werden gezwungen, sofort und von e.printStackTrace() behandelt.
  • InterruptedException in SingleCallableWorker.call() geworfen wird durch innere syncronizer in FutureTask, die syncronizer nur Rekord InterruptedException und Rückkehr werden catched . Wenn future.get() aufgerufen wird, wird die InterruptedException als ExecutionException Wrappered und erneut ausgelöst.