tri avec multithread

/**
 * Tri d'un tableau d'entiers multi-thread.
 * Utilisation de wait() et notifyAll() au lieu de join()
 */
public class Trieur extends Thread {

  private int[] t; // tableau a trier
  private int debut, fin; // tranche de ce tableau qu'il faut trier
  private Trieur parent;  // tread Trieur qui a lance ce (this) Trieur
  private int nbNotify = 0; // Nombre de notifys envoyes a ce (this) Trieur

  public Trieur(int[] t) {
    this(null, t, 0, t.length - 1);
  }
 
  private Trieur(Trieur parent, int[] t, int debut, int fin) {
    this.parent = parent;
    this.t = t;
    this.debut = debut;
    this.fin = fin;
    start();
  }

  public synchronized void notifier() {
    // Notifie tous les thread en attente sur "ce" (this) moniteur
    // Attention, quand le message sera envoye au parent (dans run()),
    // on incrementera la variable nbNotify du parent (qui sera le this
    // implicite) et on notifiera le parent.
    // On peut aussi ne pas utiliser de methode mais dans ce cas, il faut
    // ecrire parent.nbNotify++; parent.notifyAll(); dans un bloc
    // synchronise sur parent place dans la methode run (a la place de
    // "parent.notifier()").
    this.nbNotify++;
    this.notifyAll();
  }

  public void run() {
    if (fin - debut < 2) {
      if (t[debut] > t[fin]) {
        echanger(debut, fin);
      }
    }
    else {
      int milieu = debut + (fin - debut) / 2;
      Trieur trieur1 = new Trieur(this, t, debut, milieu);
      Trieur trieur2 = new Trieur(this, t, milieu + 1, fin);
      // attend les 2 threads
      synchronized(this) {
        try {
  // Tant que 2 notifications n'ont pas ete recues (1 par
  // trieur "fils"), on attend.
          while (nbNotify < 2) {
            wait();
          }
        }
        catch(InterruptedException e) {}
      }
      triFusion(debut, fin);
    }
    if (parent != null) {
      parent.notifier(); // indique qu'il a fini au parent qui l'attend
    }
  }

  /**
   * Echanger t[i] et t[j]
   */
  private void echanger(int i, int j) {
    int valeur = t[i];
    t[i] = t[j];
    t[j] = valeur;
  }

  /**
   * Fusionne 2 tranches deja triees du tableau t.
   *   - 1ere tranche : de debut au milieu = (debut + fin) / 2
   *   - 2eme tranche : de milieu a 1 la fin
   * @param debut premier indice de la 1ere tranche
   * @param fin dernier indice de la 2eme tranche
   */
  private void triFusion(int debut, int fin) {
    // tableau ou va aller la fusion
    int[] tFusion = new int[fin - debut + 1];
    int milieu = (debut + fin) / 2;
    // Indices des elements a comparer
    int i1 = debut,
        i2 = milieu + 1;
    // indice de la prochaine case du tableau tFusion a remplir
    int iFusion = 0;
    while (i1 <= milieu && i2 <= fin) {
      if (t[i1] < t[i2]) {
        tFusion[iFusion++] = t[i1++];
      }
      else {
        tFusion[iFusion++] = t[i2++];
      }
    }
    if (i1 > milieu) {
      // la 1ere tranche est epuisee
      for (int i = i2; i <= fin; ) {
        tFusion[iFusion++] = t[i++];
      }
    }
    else {
      // la 2eme tranche est epuisee
      for (int i = i1; i <= milieu; ) {
        tFusion[iFusion++] = t[i++];
      }
    }
    // Copie tFusion dans t
    for (int i = 0, j = debut; i <= fin - debut; ) {
      t[j++] = tFusion[i++];
    }
  }
  public static void main(String[] args) {
    int[] t = {5, 8, 3, 2, 7, 10, 1};
    Trieur trieur = new Trieur(t);
    try {
      trieur.join();
    }
    catch(InterruptedException e) {}
      for (int i = 0; i <t.length; i++) {
     System.out.print(t[i] + " ; ");
     }
    System.out.println("Done");
  }

}

Commentaires