2010-10-12 21 views
4

Code de l'ouvrage "Java Concurrency in Practice" Listing 8.1Pourquoi est-il l'impasse

Pourquoi le code est la supercondamnation? Est-ce parce que le rpt.call dans main() est fondamentalement le même fil que celui dans Executors?

Même si j'utilise 10 threads pour exec = Executors.newFixedThreadPool(10); il reste encore des blocages?

public class ThreadDeadlock { 
    ExecutorService exec = Executors.newSingleThreadExecutor(); 

    public class RenderPageTask implements Callable<String> { 
    public String call() throws Exception { 
     Future<String> header, footer; 
     header = exec.submit(new LoadFileTask("header.html")); 
     footer = exec.submit(new LoadFileTask("footer.html")); 
     String page = renderBody(); 
     // Will deadlock -- task waiting for result of subtask 
     return header.get() + page + footer.get(); 
    } 
    } 

    public static void main(String [] args) throws Exception { 

     ThreadDeadlock td = new ThreadDeadlock(); 
     ThreadDeadlock.RenderPageTask rpt = td.new RenderPageTask(); 
     rpt.call(); 
    } 
} 

Répondre

9

Votre code n'interblocage pas - le fait de suivre:

public class ThreadDeadlock { 
    ...  
    public static void main(String [] args) throws Exception { 
     ThreadDeadlock td = new ThreadDeadlock(); 
     ThreadDeadlock.RenderPageTask rpt = td.new RenderPageTask(); 

     Future<String> f = td.exec.submit(rpt); 

     System.out.println(f.get()); 
     td.exec.shutdown(); 
    } 
} 

Cela se produit si vous soumettez plusieurs tâches simultanées à l'exécuteur testamentaire de fil unique, lorsque la première tâche attend le résultat de la les suivants. Il ne se bloque pas avec Executors.newFixedThreadPool(2) parce que LoadFileTask s sont indépendants et peuvent partager un fil quand un autre est utilisé par RenderPageTask.

Le point de cet exemple est que si vous soumettez des tâches interdépendantes au ExecutorService, vous devez vous assurer que la capacité du pool de threads est suffisante pour les exécuter avec le niveau de parallélisme requis.

+0

Je pense que vous auriez dû ajouter que le code original ne se termine pas parce qu'il y a un exécuteur qui attend la nouvelle tâche et il suffit d'ajouter 'td.exec.shutdown();' comme dernière instruction de main dans afin de le finir. – mykola