2016-07-19 6 views
0

simultané Si j'utilise Futures commeUtilisation de shutdownNow dans le cadre

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

ou

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

le système attend les tâches à accomplir. Même si j'ai eu executorService.shutdownNow(); après les instructions mentionnées ci-dessus, je ne comprends vraiment pas quand le système mettra fin aux threads existants comme mentionné dans la documentation puisque, le système n'atteindra jamais la ligne jusqu'à ce que les tâches soient terminées et un avenir est renvoyé. Ai-je raté quelque chose? Existe-t-il un scénario de test différent pour le tester?

shutdownNow fonctionnera-t-il uniquement avec Runnable, c'est-à-dire lorsque nous disons executorService.submit(new MyRunnable())?

EDIT:

J'ai essayé quelques choses différentes et a trouvé que

a) shutdownNow ne fonctionne pas avec invokeAll.

b) shutdownNow si elle est présente après Future.get alors la déclaration shutdownNow est bloquée jusqu'à ce que Future est résolu (En cas de Callable).

c) shutdownNow fonctionne parfaitement avec Runnable.

Après mon code écrit à tester:

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"; 
    } 

} 

et je teste comme suit:

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(); 

où les tâches sont tous Callables.

La ligne de fond est invokeAll et Future.get sont des opérations de blocage. Quelqu'un peut-il valider s'il vous plaît?

+2

Vraisemblablement, il y a des threads séparés faisant 'Future # get()'. –

+1

"terminer avec force?" pas vraiment, lisez le doc: "Il n'y a aucune garantie au-delà des tentatives de meilleur effort pour arrêter le traitement des tâches d'exécution active.Par exemple, les implémentations typiques seront annulées via Thread.interrupt(), donc toute tâche qui échoue à répondre aux interruptions ne peut jamais se terminer " –

Répondre

1

Les deux Runnbale et Callable que vous avez soumis à ThreadPoolExecutor seront encapsulés comme java.util.concrrent.FutureTask et seront exécutés.

Dans ce cas, dans les deux SingleRunnableWorker et SingleCallableWorker, lorsque la tâche est bloquée par Thread.sleep(10000), executorService.shutdownNow() provoquera InterruptedException être jeté immédiatement.

Mais,

  • InterruptedException jeté SingleRunnableWorker.run() est forcé d'être attrapée immédiatement et traitées par e.printStackTrace().
  • InterruptedException jeté SingleCallableWorker.call() sera être par synchroniseur interne attrapé dans FutureTask, le synchroniseur juste enregistrement InterruptedException et retour. Lorsque future.get() est appelée, l'exception InterruptedException sera encapsulée en tant que ExecutionException et relancée. `ShutdownNow` essayera d'arrêter les threads exécutant le travail que vous soumettez au` ExecutorService` correspondant.