2017-08-28 6 views
1

Je suis en train de mettre en œuvre un programme fictif avec trois classes pour avoir une référence plus visuelle de la façon dont fonctionne Future. Mon problème est que parfois le programme sera verrouillé à la méthode synchronisée et il ne continuera pas. Et je ne peux pas trouver de raison pour ça. Quelqu'un peut-il repérer la raison pour laquelle aucun des combattants n'imprime la ligne «J'ai gagné»?Exécution de blocs de méthodes synchronisées

Ma sortie courant lorsqu'il bloque:

Fighter1

Fighter1 est entré dans le procédé de synchronisation

Fighter2

Fighter2 est entré dans le procédé de synchronisation

Le le code est le suivant.

Classe principale:

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

public class TmpTest { 
private static final ExecutorService executorService = 
    Executors.newFixedThreadPool(2); 

    public static void main(final String... args) { 

    final Fighter fighter1 = new Fighter("Fighter1"); 
    final Fighter fighter2 = new Fighter("Fighter2"); 

    final Future<String> submitFighter1 = executorService.submit(fighter1); 
    final Future<String> submitFighter2 = executorService.submit(fighter2); 

    while (!submitFighter1.isDone() || !submitFighter2.isDone()) { 
     if (submitFighter1.isDone()) { 
      System.out.println("Fighter 1 wins!"); 
      submitFighter2.cancel(true); 
      executorService.shutdown(); 
     } else if (submitFighter2.isDone()) { 
      submitFighter1.cancel(true); 
      System.out.println("Fighter 2 wins!"); 
      executorService.shutdown(); 
     } 
    } 
    } 
} 

classe Fighter:

class Fighter implements Callable<String> { 

    private final String fighterName; 
    private final ClassWithSyncMethod classWithSyncMethod; 

    public Fighter(final String fighterName) { 
    this.fighterName = fighterName; 
    classWithSyncMethod = new ClassWithSyncMethod(fighterName); 
    } 

    @Override 
    public String call() throws Exception { 
    return classWithSyncMethod.syncMethod(); 
    } 
} 

classe factice avec méthode synchronisée:

class ClassWithSyncMethod { 

    private final String fighterName; 

    public ClassWithSyncMethod(final String fighterName) { 
    this.fighterName = fighterName; 
    } 

    public synchronized String syncMethod() { 
    System.out.println(fighterName + " has entered the sync method"); 
    try { 
     Thread.sleep(1000); 
    } catch (final InterruptedException e) { 
     System.out.println("Exception trying to sleep the fighter " + fighterName + ";" + e); 
    } 
    return fighterName + " shouts: I won!"; 
    } 
} 

Répondre

3

Cela n'a rien à voir avec la synchronisation. Chaque combattant se synchronise sur un objet différent, de sorte qu'ils n'interfèrent pas les uns avec les autres.

La raison pour laquelle vous ne voyez pas la ligne "J'ai gagné" est beaucoup plus simple - vous ne l'imprimez jamais. La méthode ClassWithSyncMethod#syncMethod() (renvoyée par Fighter#call()) n'imprime rien, elle renvoie simplement une valeur. Si vous voulez l'imprimer, vous devrez le faire vous-même à partir de votre main.

.: par exemple

while (!submitFighter1.isDone() || !submitFighter2.isDone()) { 
    if (submitFighter1.isDone()) { 
     System.out.println("Fighter 1 wins!"); 
     System.out.println(submitFighter1.get()); // Here! 
     submitFighter2.cancel(true); 
     executorService.shutdown(); 
    } else if (submitFighter2.isDone()) { 
     submitFighter1.cancel(true); 
     System.out.println("Fighter 2 wins!"); 
     System.out.println(submitFighter2.get()); // And here! 
     executorService.shutdown(); 
    } 
} 
+0

Vous êtes tout à fait raison. Je suis un idiot. Merci! – Tavo

+1

Point clé droit 'Chaque combattant se synchronise sur un objet différent, +1 pour vous –