SemaConcurrent.java

package fr.umlv.ji.tcp.server;
import java.util.logging.*;
import java.util.prefs.*;
import java.net.*;
import java.io.*;
/**
 * Classe pour un serveur concurrent utilisant un compteur, protégé
 * par sémaphore, pour limiter le nombre de processus légers
 * traitant les connexions des clients.
 */
public class SemaConcurrent extends Concurrent {
  /** Compteur du nombre de processus légers acceptés. */
  protected SemaMultiple sem;
  /** Constructeur du serveur. */
  public SemaConcurrent(Logger log, Preferences prefs) {
    super(log,prefs);
  }
  /** Méthode affectant le nombre maximum de processus légers. */
  public void setThreadNumber(int maxTread) {
    sem = new SemaMultiple(maxTread);
  }
  /** Spécialisation de la méthode launch() de Concurrent. */
  public void launch() {
    if (sem==null) {
      int maxTread = preferences.getInt("maxThread",10);
      sem = new SemaMultiple(maxTread);
    }
    super.launch();
  }
  /** Redéfinition de la méthode runnableService(). Cette méthode, qui
      est appelée par la méthode launch() héritée de Concurrent, doit
      être redéfinie ici pour incrémenter et décrémenter le sémaphore
      limitant le nombre de processus légers créés. */
  Runnable runnableService(final Socket serviceSocket) {
    // Avant toute chose, cette méthode tente de décrémenter le
    // sémaphore.  Ainsi, si le nombre maximum de processus légers est
    // atteint, cette méthode bloque la création de l'objet à
    // retourner et bloque donc la création du nouveau processus léger
    // dans launch().
    try {
      sem.P();
    } catch (InterruptedException e) {
      // Permet d'arrêter le processus léger courant proprement
      return null;
    }
    // Retourne un objet implantant Runnable, dont la méthode run()
    // sera exécutée par le processus léger qui l'accepte en argument
    return new Runnable() {
      public void run() {
    try {
      logger.info("Exécution d'un service dans le processus léger"
              + Thread.currentThread());
      service.serve(serviceSocket);
      serviceSocket.close();
    } catch (IOException e) {
      logger.log(Level.SEVERE,"Service call",e);
    } finally {
      // Quelque soit le comportement, on incrémente le sémaphore
      // le plus tard possible dans la méthode run() (à la fin de
      // l'exécution du processus léger)
      sem.V();
    }
      }
    };
  }
}