2010-08-01 10 views
4

Ecrivez une classe nommée RaceHorse qui étend le fil. Chaque RaceHorse a un nom et une méthode run() qui affiche le nom 5000 fois. Ecrivez une application Java qui instancie deux objets RaceHorse. Le dernier RaceHorse à finir est le perdant.Aide nécessaire en Multithreading pour déterminer quel thread s'arrête en premier

C'est la question. J'ai écrit le code pour les deux classes de deux exécuter le fil Voici les codes: - RaceHorse

class RaceHorse extends Thread 
{ 
    public String name; 
    public RaceHorse(String name) 
    { 
     this.name = name; 
    } 
    public void run() 
    { 
     for(int i = 1 ; i <= 5000; i++) 
     { 
      System.out.println(i+" "+name); 
     } 
     System.out.println(name+" finished."); 
    } 
} 

Runner

class Runner{ 
    public static void main(String args[]) 
    { 
     RaceHorse obj = new RaceHorse("Lol"); 
     RaceHorse obj2 = new RaceHorse("BOL"); 
     Thread t = new Thread(obj); 
     Thread t2 = new Thread(obj2); 
     t.start(); 
     t2.start(); 
    } 
} 

* Maintenant, mon problème est que je ne peux pas trouver quel fil finit le premier et quelle seconde, c'est-à-dire lequel du cheval gagne et qui perd. Alors, s'il vous plaît, aidez-moi. * forte texte

+4

Alors * c'est * pourquoi on appelle une « race condition » – finnw

Répondre

10

Tout d'abord: vos objets RaceHorse sont eux-mêmes des threads. Vous devriez être capable de dire obj.start(); et ça marcherait aussi bien. Supprimez donc t et t2 entièrement.

Ensuite, vous aurez besoin d'un moyen d'informer le thread principal sur le gagnant.

public void run() 
{ 
    ... your loop stuff ... 
    // this is how we're going to do the notification. 
    Runner.done(); 
} 

public class Runner 
{ 
    private static RaceHorse winner = null; 
    synchronized static void done() 
    { 
     // Threads calling this are going to be RaceHorse objects. 
     // Now, if there isn't already a winner, this RaceHorse is the winner. 
     if (winner == null) winner = (RaceHorse) Thread.currentThread(); 
    } 

    public static void main(String[] args) 
    { 
     ... create the horses ... 
     // start the horses running 
     obj.start(); 
     obj2.start(); 

     // wait for them to finish 
     obj.join(); 
     obj2.join(); 

     System.out.println(winner.name + " wins!"); 
    } 
} 
+0

+1 Nice et soignée. – sje397

+0

+1 c'est une façon NICE de gérer ce problème. –

+0

thnx bro vous avez résolu mon problème Merci beaucoup.! –

1
public class StackOverflow { 

    public static void main(String[] args) { 
     RaceHorse obj = new RaceHorse("Lol"); 
      RaceHorse obj2 = new RaceHorse("BOL"); 
      Thread t = new Thread(obj); 
      Thread t2 = new Thread(obj2); 
      t.start(); 
      t2.start(); 

    }  
    } 
class RaceHorse extends Thread 
{ 
    //public String name; 
    public RaceHorse(String name) 
    { 
     this.setName(name); 
    } 
    public void run() 
    { 
     for(int i = 1 ; i <= 5000; i++) 
     { 
      System.out.println(i+" "+this.getName()); 
      try { 
       Thread.sleep(250); 
      } catch (InterruptedException e) { 

       e.printStackTrace(); 
      } 
     } 
     System.out.println(this.getName()+" finished."); 
    } 
} 
+0

bro voir la question correctement je dois créer deux objets de la classe RaceHorse puis effectuez une course que je l'ai fait. Mais où appliquer ces thread.setName (""); et thread.getName(); fonctions cos les deux threads seront en cours d'exécution. Et je veux savoir quel fil s'arrête en premier, fil t ou fil t2. En conséquence, je vais afficher le gagnant et le perdant. –

+1

Pls checkout mon code. –

+0

Le flux de sortie standard n'est généralement pas adapté à la gestion de plusieurs threads. Je ne compterais pas là-dessus pour déterminer le gagnant. – sje397

6

Il n'y a aucun doute une meilleure façon, mais une méthode peut-être créer une classe (par exemple, « Trophy ») qui est thread-safe, a une méthode « getTrohpy » qui renvoie uniquement vrai sur le premier appel, et passez une référence à une instance de Trophy aux deux threads.

0

Je ne vais pas écrire le code pour vous; mais vous devriez jeter un oeil à la méthode notify (voir here) à utiliser.

Une approche peut être: une fois qu'un thread est terminé, wait() pour les autres threads à notifier (ou notifyAll()).

Une autre solution, plus élégante, consisterait à utiliser un bloc synchronized sur un objet partagé; l'instruction syncrhonized(obj) serait à la fin de la méthode run(). Dans cette déclaration, vous pouvez mettre une ligne d'impression ou tout autre code que vous jugerez utile pour déterminer qui a gagné la course.

0

Cela fonctionne à la fin de la principale:

boolean alive1 = true; 
boolean alive2 = true; 

while (alive1 && alive2) { 
    alive1 = obj.isAlive(); 
    alive2 = obj2.isAlive(); 
    if (!alive1 && !alive2) { 
     // Too close to call 
    } 
    if (!alive1) { 
     // obj wins, 
    } 
    if (!alive2) { 
     // obj2 wins, 
    } 
} 
1

Comme chao a souligné, RaceHorse étend Thread mais vous créez un nouveau Thread par cheval. Je voudrais résoudre le contraire, en ayant RaceHorse mettre en œuvre Runnable à la place.

Deuxièmement, la solution utilisant une méthode synchronized fonctionnera, mais une règle générale est toujours de chercher une classe dans java.util.concurrent qui résoudra le problème en premier. Celui-ci peut être résolu en utilisant un AtomicReference pour s'assurer qu'un seul cheval prend le trophée.Enfin, il pourrait y avoir un biais en faveur du cheval # 1, si le fil principal commence les fils des chevaux dans un ordre fixe (cela dépend de la VM et du temps de démarrage d'un nouveau thread sur votre système d'exploitation).) Envisagez d'utiliser un signal (par exemple un CountDownLatch) que tous les chevaux attendent avant de commencer.

import java.util.concurrent.CountDownLatch; 
import java.util.concurrent.atomic.AtomicReference; 

public class Runner { 

    public static void main(String args[]) { 
     AtomicReference<RaceHorse> winner = 
      new AtomicReference<RaceHorse>(); 
     CountDownLatch startingPistol = new CountDownLatch(1); 
     RaceHorse horse1 = new RaceHorse("Lol", startingPistol, winner); 
     RaceHorse horse2 = new RaceHorse("BOL", startingPistol, winner); 
     Thread thread1 = new Thread(horse1); 
     Thread thread2 = new Thread(horse2); 
     thread1.start(); 
     thread2.start(); 
     startingPistol.countDown(); 
    } 

} 

class RaceHorse implements Runnable { 

    private final String name; 
    private final CountDownLatch startingPistol; 
    private final AtomicReference<RaceHorse> winner; 

    public RaceHorse(String      name, 
        CountDownLatch    startingPistol, 
        AtomicReference<RaceHorse> winner) 
    { 
     this.name = name; 
     this.startingPistol = startingPistol; 
     this.winner = winner; 
    } 

    public void run() 
    { 
     try { 
      startingPistol.await(); 
      for(int i = 1 ; i <= 5000; i++) 
      { 
       System.out.println(i+" "+name); 
      } 
      boolean iWon = winner.compareAndSet(null, this); 
      System.out.printf("%s %s.%n", name, iWon? "won": "lost"); 
     } catch (InterruptedException ex) { 
      System.out.printf("%s was assasinated before the race started.%n", name); 
      Thread.currentThread().interrupt(); 
     } 
    } 

} 
+2

La spécification elle-même indique 'RaceHorse' * must * extends' Thread'. – cHao

+0

+1 pour le CountDownLatch, c'est exactement ce que je suis venu chercher ici! –

0

Je suis en retard à la fête, mais je trouve cela tout en recherchant la façon de traiter le premier résultat d'un certain nombre de threads en cours d'exécution. Je pense que la façon la plus simple est d'utiliser une ArrayBlockingQueue qui vous donne quelque chose comme ça.

public class RaceHorse extends Thread { 
     private ArrayBlockingQueue<RaceHorse> finishedRaceHorses; 

     public RaceHorse(String name) { 
      super(name); 
     } 

     public void run() { 
      for (int i = 1; i <= 50; i++) { 
       System.out.println(i + " " + getName()); 
      } 
      System.out.println(getName() + " finished."); 

      finishedRaceHorses.offer(this); 
     } 

     public void setFinishedRaceHorses(ArrayBlockingQueue<RaceHorse> finishedRaceHorses) { 
      this.finishedRaceHorses = finishedRaceHorses; 
     } 
    } 

    public class Race { 
     private final List<RaceHorse> raceHorses; 

     public Race(List<RaceHorse> raceHorses) { 
      this.raceHorses = raceHorses; 
     } 

     public RaceHorse go() throws InterruptedException { 
      ArrayBlockingQueue<RaceHorse> finishedRaceHorses = new ArrayBlockingQueue<RaceHorse>(raceHorses.size()); 
      for (RaceHorse raceHorse : raceHorses) { 
       raceHorse.setFinishedRaceHorses(finishedRaceHorses); 
       raceHorse.start(); 
      } 

      return finishedRaceHorses.take(); 
     } 
    } 

public class Runner { 
    public static void main(String args[]) 
    { 
     RaceHorse horseOne = new RaceHorse("Lol"); 
     RaceHorse horseTwo = new RaceHorse("BOL"); 

     Race race = new Race(Arrays.asList(horseOne, horseTwo)); 
     try { 
      RaceHorse winner = race.go(); 
      System.out.println("The winner is " + winner.getName()); 
     } catch (InterruptedException e) { 
      System.out.println("The race was interrupted, maybe by a streaker?"); 
     } 
    } 
} 
0
I have tried this problem and solved it using following code. There is room for improvement but for me this code worked perfectly : 

1.RacingGame.java 
/
package game; 

import gamingObject.Horse; 
import gamingObject.Race; 

import java.util.ArrayList; 
import java.util.Arrays; 
import java.util.HashMap; 
import java.util.Iterator; 
import java.util.List; 
import java.util.Map; 
import java.util.concurrent.Executor; 
import java.util.concurrent.ExecutorService; 
import java.util.concurrent.Executors; 

public class RacingGame { 

    /** 
    * @param args 
    */ 

    public static Map<Integer, List<String>> raceToWinners = new HashMap<Integer, List<String>>(); 
    public static int currentRace = 1; 
    public static boolean trackComplete = false; 
    private static boolean newTrackBegin; 
    private static boolean flag = true; 
    private static boolean race6Begin = false; 
    private static boolean race7Begin = false; 
    private static Object mutex = new Object(); 
    private int frstHorseInNextRace = 0; 

    public static void main(String[] args) throws InterruptedException { 
     ExecutorService exeService = Executors.newFixedThreadPool(5); 
     /* 
     * Logic to conduct first 5 races (total horses/total track) so here 
     * total horses = 25 and tracks = 5 hence initial and compolsuary races 
     */ 

     RacingGame rg = new RacingGame(); 

     for (int race = 1; race <= 5; race++) { 
      trackComplete = false; 
      currentRace = race; 
      while (!trackComplete) { 
       rg.startTrack(); 
      } 
     } 
     /* 
     * Before 6th Race lets have right candidate for 6th race 
     */ 
     List<String> horseNames = chooseHorsesForRace6(); 

     /* 
     * Race among 5 tops horses from 5 races 
     */ 
     currentRace++; 
     synchronized (mutex) { 
      while (!race6Begin) { 
       race(horseNames); 
      } 
     } 

     /* 
     * Choose candidates for last race 7 
     */ 
     horseNames = chooseHorsesForRace7(); 

     currentRace++; 
     synchronized (mutex) { 
      while (!race7Begin) { 
       race(horseNames); 
      } 
     } 

     printResults(); 

     System.exit(0); 
    } 

    private static void printResults() { 
     // TODO Auto-generated method stub 
     Iterator<Integer> iter = raceToWinners.keySet().iterator(); 
     while (iter.hasNext()) { 
      int raceNum = iter.next(); 
      StringBuffer sb = new StringBuffer(); 
      System.out.println("Race" + raceNum + " : "); 
      List<String> horses = raceToWinners.get(raceNum); 
      for (int i = 0; i < 3; i++) { 
       sb.append(horses.get(i)); 
       if (i < 2) 
        sb.append(","); 
      } 
      System.out.print(sb.toString()); 
      System.out.println(); 
     } 
    } 

    private static List<String> chooseHorsesForRace7() { 
     /* 
     * Adding First horse at first rank among 25 horses 
     */ 
     List<String> winners = new ArrayList<String>(); 
     winners.add(raceToWinners.get(6).get(0)); 
     raceToWinners.put(7, winners); 
     /* 
     * Taking first horses from races 2 and 3 
     */ 
     List<String> finalTrackHorses = new ArrayList<String>(); 
     finalTrackHorses.add(raceToWinners.get(6).get(1));// firstHorse 
     finalTrackHorses.add(raceToWinners.get(6).get(2));// secondHorse 
     /* 
     * Rejecting all horses from race track whose first horses are at 4th 
     * and 5th rank of race 6 
     */ 
     for (int i = 1; i <= 5; i++) { 
      if (raceToWinners.get(i).contains(winners.get(0))) { 
       finalTrackHorses.add(raceToWinners.get(i).get(1));// thirdHorse 
       finalTrackHorses.add(raceToWinners.get(i).get(2));// forth horse 
      } else if (raceToWinners.get(i).contains(finalTrackHorses.get(1))) { 
       finalTrackHorses.add(raceToWinners.get(i).get(1));// fifth horse 
      } 
     } 
     return finalTrackHorses; 
    } 

    private static void race(List<String> horseNames) throws InterruptedException { 
     if (currentRace == 6) 
      race6Begin = true; 
     else 
      race7Begin = true; 
     newTrackBegin = true; 
     flag = true; 
     trackComplete = false; 
     while (flag) { 
      if (!trackComplete) { 
       /* 
       * Create thread for each horse 
       * 
       * Here taking slot of 5 horses and keep them running in a 
       * single loop. 
       */ 
       if (newTrackBegin) { 
        List<String> horses = Arrays.asList(horseNames.get(0), 
          horseNames.get(1), horseNames.get(2), 
          horseNames.get(3), horseNames.get(4)); 
        Race r = new Race(horses); 
        r.start(); 
       } 
       newTrackBegin = false; 
       mutex.wait(1); 

      } else if (trackComplete) { 
       mutex.notify(); 
       flag = false; 
      } 

     } 

    } 

    private static List<String> chooseHorsesForRace6() { 
     List<String> lstHorses = new ArrayList<String>(); 
     for (int i = 1; i <= 5; i++) { 
      /* 
      * Take only 1st Position Holders of first 5 races 
      */ 
      lstHorses.add(raceToWinners.get(i).get(0)); 
     } 
     return lstHorses; 
    } 

    public Map<Integer, List<String>> getRaceToWinners() { 
     return raceToWinners; 
    } 

    public static synchronized void addTrackWinnerInList(String horseName) { 
     List<String> horses = raceToWinners.get(currentRace); 
     if (horses == null) { 
      List<String> raceHorses = new ArrayList<String>(); 
      raceHorses.add(horseName); 
      raceToWinners.put(currentRace, raceHorses); 
     } else { 
      horses.add(horseName); 
      raceToWinners.put(currentRace, horses); 
     } 
     if (raceToWinners.get(currentRace) != null 
       && raceToWinners.get(currentRace).size() == 5) { 
      trackComplete = true; 
     } 
    } 

    public static boolean isTrackComplete(){ 
     return trackComplete; 
    } 

    public void startTrack() throws InterruptedException { 
     // TODO Auto-generated method stub 
     synchronized (mutex) { 
      flag = true; 
      newTrackBegin = true; 
      trackComplete = false; 
      while (!trackComplete) { 
       /* 
       * Create thread for each horse 
       * 
       * Here taking slot of 5 horses and keep them running in a 
       * single loop. 
       */ 
        if (newTrackBegin) { 
         List<String> horses = Arrays.asList("Horse" 
           + (++frstHorseInNextRace), "Horse" 
           + (++frstHorseInNextRace), "Horse" 
           + (++frstHorseInNextRace), "Horse" 
           + (++frstHorseInNextRace), "Horse" 
           + (++frstHorseInNextRace)); 
         Race r = new Race(horses); 
         r.start(); 
        } 
        newTrackBegin = false; 

      } 

     } 

    } 

} 


2.Horse.java 

    package gamingObject; 

import game.RacingGame; 

public class Horse extends Thread{ 

    String horseName; 

    public Horse(String horseName){ 
     this.horseName = horseName; 
    } 

    @Override 
    public void run() { 
     for (int i = 0; i < 5; i++) { 
      try { 
       sleep(1); 
      } catch (InterruptedException e) { 
       // TODO Auto-generated catch block 
       e.printStackTrace(); 
      } 
     } 
     RacingGame.addTrackWinnerInList(this.horseName); 
    } 

} 

3.Race.java 

    package gamingObject; 

import game.RacingGame; 

import java.util.List; 

public class Race extends Thread { 

    List<String> horses; 
    private boolean flag = true; 
    private Object obj = new Object(); 

    public Race(List<String> horses) { 
     this.horses = horses; 
    } 

    public void startRace() { 
     synchronized (obj) { 
      run(); 
     } 
    } 

    @Override 
    public void run() { 
     synchronized (obj) { 
      boolean newTrackBegin = true; 

      while (!RacingGame.isTrackComplete()) { 
        /* 
        * Create thread for each horse 
        * 
        * Here taking slot of 5 horses and keep them running in a 
        * single loop. 
        */ 
        if (newTrackBegin) { 
         Horse h1 = new Horse(horses.get(0)); 
         Horse h2 = new Horse(horses.get(1)); 
         Horse h3 = new Horse(horses.get(2)); 
         Horse h4 = new Horse(horses.get(3)); 
         Horse h5 = new Horse(horses.get(4)); 
         Thread t1 = new Thread(h1); 
         Thread t2 = new Thread(h2); 
         Thread t3 = new Thread(h3); 
         Thread t4 = new Thread(h4); 
         Thread t5 = new Thread(h5); 
         t1.start(); 
         t2.start(); 
         t3.start(); 
         t4.start(); 
         t5.start(); 
         newTrackBegin = false; 
        }else{ 
         if(!RacingGame.isTrackComplete()){ 
          try { 
           obj.wait(10); 
          } catch (InterruptedException e) { 
           // TODO Auto-generated catch block 
           e.printStackTrace(); 
          } 
         }else{ 
          obj.notify(); 
         } 

        } 

      } 

     } 
    } 

}