page précédantetable des matières

Threads
Java est un langage dit multithreads, ce qui signifie qu'a un instant donné une application peut avoir plusieurs threads qui s'exécutent. Un thread est un système d'exécution séparé dans un même programme. Les threads fournissent les moyens à une application d'effectuer beaucoup de tâches différentes en même temps. Si une application effectue n'importe quel type de traitement important, comme une animation, un calcul long, il sera bien de créer des threads distincts pour chacun de ces traitement.

Conceptuellement les threads ressemblent à des processus, à la différence que plusieurs threads partagent le même espace d'adressage, se qui signifie qu'ils peuvent partager des variables et des méthodes (en possédant en même temps ses propres variables locales).

Les threads sont plus économes en ressources si on les compare au processus, donc il est concevable pour une seule application de lancer des centaines de threads en même temps

Interface non accessible
 
 
 //: CompteurNA.java
// A non-responsive user interface
//package c14;
import java.awt.*;
import java.awt.event.*;
import java.applet.*;

public class CompteurNA extends Applet {
  private int count = 0;
  private Button
  onOff = new Button("Stop"),
  start = new Button("Start");
  private TextField t = new TextField(10);
  private boolean runFlag = true;
  public void init() {
  add(t);
  start.addActionListener(new StartL());
  add(start);
  onOff.addActionListener(new OnOffL());
  add(onOff);
  }
  public void go() {
  while (true) {
  try {
    Thread.currentThread().sleep(100);
  } catch (InterruptedException e){}
  if(runFlag)
    t.setText(Integer.toString(count++));
  }
  }
 

CompteurNA:

  class StartL implements ActionListener {
  public void actionPerformed(ActionEvent e) {
  go();
  }
  }
  class OnOffL implements ActionListener {
  public void actionPerformed(ActionEvent e) {
  runFlag = !runFlag;
  }
  }
  public static void main(String[] args) {
      CompteurNA applet = new CompteurNA();
      Frame aFrame = new Frame("CompteurNA");
      aFrame.addWindowListener(  new WindowAdapter() {
            public void windowClosing(WindowEvent e) {
                System.exit(0);
            }
      });
      aFrame.add(applet, BorderLayout.CENTER);
      aFrame.setSize(300,200);
      applet.init();
      applet.start();
      aFrame.setVisible(true);
  }
}
 
 

Dériver la classe Thread


La programmation avec les threads a des particularités surtout avec la synchronisation des threads. Java a des utiles simples pour résoudre bon nombre de problè-mes.

Les threads sont créés et contrôlé par les objets de la classe Thread.

Chaque objet de ce classe correspond à un seul thread. Il contient des méthodes pour lancer, contrôler et arrêter l'exécution du thread. Pour lancer l'exécution  d'un thread on doit appeler la méthode start() de la classe Thread. Une fois que le thread est lancé, il continue à s'exécuter jusqu'à la fin du traitement (indiqué par la méthode run() ) ou jusqu'à ce que la méthode stop() le termine.

Le traitement qui doit être effectué par le thread est indiqué par une méthode appelée run(). On a deux possibilités pour spécifier la méthode run(). Premièrement, la classe Thread elle-même possède une méthode run(). On peut dériver la classe Thread et de redéfinir sa méthode run() pour faire ce que l'on veut. Dans ce cas on crée une instance de la classe dérivée et on lance sa méthode start().

 

//: SimpleThread.java
// Very simple Threading example

public class SimpleThread extends Thread {
  private int countDown = 5;
  private String name;
  private static int threadCount =  0;
  public SimpleThread(String nameP) {
  name = nameP;
  System.out.println("Making " + name);
  }
  public void run() {
  for( ;countDown>0; countDown--) {
  System.out.println("Thread " +
    name + "(" + countDown + ")");
  }
  System.out.println("Thread " + name + " end");
  }
  public static void main(String[] args) {
  String nameA[]={"Nick", "Marie",
   "George", "Isabelle", "Pierre"};
  for(int i = 0; i < 5; i++)
  new SimpleThread(nameA[i]).start();
  System.out.println("All Threads Started");
  }
}

java SimpleThread


Making Nick
Making Marie
Making George
Making Isabelle
Making Pierre
All Threads Started
Thread Nick(5)
Thread Marie(5)
Thread George(5)
Thread Isabelle(5)
Thread Pierre(5)
Thread Nick(4)
Thread Marie(4)
Thread George(4)
Thread Isabelle(4)
Thread Pierre(4)
Thread Nick(3)
Thread Marie(3)
Thread George(3)
Thread Isabelle(3)
Thread Pierre(3)
Thread Nick(2)
Thread Marie(2)
Thread George(2)
Thread Isabelle(2)
Thread Pierre(2)
Thread Nick(1)
Thread Marie(1)
Thread George(1)
Thread Isabelle(1)
Thread Pierre(1)
Thread Nick end
Thread Marie end
Thread George end
Thread Isabelle end
Thread Pierre end

 


Interface accessible

Il n'est pas toujours possible de créer une classe dérivée de la classe Thread. Par exemple une applet doit être dérivée de la classe Applet, donc elle ne peut pas être dérivée en même temps de la classe Thread. Dans ce cas on a besoin d'indiquer à la classe Thread quel objet possède la méthode run() qu'il doit exécuter. La classe Thread possède un constructeur qui prend comme argument une référence sur un objet. Si on crée un objet thread en utilisant ce constructeur et si on appelle sa méthode start() le thread va exécuter la méthode run() de l'objet passé en paramètre plutôt que la sienne. Pour effectuer cette opération, Java a besoin d'avoir garantie que l'objet que nous passons en paramètre contient une méthode run().
 On peut utiliser un Thread qui travail tous le temps:
 
 
 //: CompteurA.java
// Using the Runnable interface to turn the
// main class into a thread.
import java.awt.*;
import java.awt.event.*;
import java.applet.*;

 public class CompteurA extends Applet implements Runnable {
        private int count = 0;
        private boolean runFlag = true;
        private Thread selfThread = null;
        private Button
                  onOff = new Button("Stop"),
                  start = new Button("Start");
        private TextField t = new TextField(10);
        public void init() {
              add(t);
              start.addActionListener(new StartL());
              add(start);
              onOff.addActionListener(new OnOffL());
              add(onOff);
         }
         public void run() {
                 while (true) {
                 try {
                     selfThread.sleep(100);
                 } catch (InterruptedException e){}
                  if(runFlag)
                  t.setText(Integer.toString(count++));
          }
  }
  class StartL implements ActionListener {
        public void actionPerformed(ActionEvent e) {
                if(selfThread == null){
                        selfThread = new Thread(CompteurA.this);
                        selfThread.start();
                }
                runFlag = true;
        }
  }
  class OnOffL implements ActionListener {
          public void actionPerformed(ActionEvent e) {
                  runFlag = false;
          }
  }
  public static void main(String[] args) {
          CompteurA applet = new CompteurA();
          Frame aFrame = new Frame("CompteurA");
          aFrame.addWindowListener(
                  new WindowAdapter() {
                            public void windowClosing(WindowEvent e) {
                                    System.exit(0);
                            }
                  }
           );
          aFrame.add(applet, BorderLayout.CENTER);
          aFrame.setSize(300,200);
          applet.init();
          applet.start();
          aFrame.setVisible(true);
    }
}

CompteurA:
 
 


 
 

Ou bien créer et tuer le Thread chaque fois:
 

//: CompteurA1.java
// Using the Runnable interface to turn the
// main class into a thread.
import java.awt.*;
import java.awt.event.*;
import java.applet.*;

public class CompteurA1
  extends Applet implements Runnable {
  private int count = 0;
private Thread selfThread = null;
  private Button
  onOff = new Button("Stop"),
  start = new Button("Start");
  private TextField t = new TextField(10);
  public void init() {
  add(t);
  start.addActionListener(new StartL());
  add(start);
  onOff.addActionListener(new OnOffL());
  add(onOff);
  }
  public void run() {
  while (true) {
  try {
    selfThread.sleep(100);
  } catch (InterruptedException e){}
  t.setText(Integer.toString(count++));
  }
  }
  class StartL implements ActionListener {
  public void actionPerformed(ActionEvent e) {
  if(selfThread == null){
    selfThread = new Thread(CompteurA1.this);
    selfThread.start();
  }
  }
  }
  class OnOffL implements ActionListener {
  public void actionPerformed(ActionEvent e) {
   if(selfThread != null) {
    selfThread.stop();
   selfThread = null;
  }
  }
}
  public static void main(String[] args) {
  CompteurA1 applet = new CompteurA1();
  Frame aFrame = new Frame("CompteurA1");
  aFrame.addWindowListener(
  new WindowAdapter() {
    public void windowClosing(WindowEvent e) {
    System.exit(0);
    }
  });
  aFrame.add(applet, BorderLayout.CENTER);
  aFrame.setSize(300,200);
  applet.init();
  applet.start();
  aFrame.setVisible(true);
  }
} ///:~
 
 

Lancement de plusieurs threads
 
 
 //: CompteurPT.java
// If you separate your thread from the main
// class, you can have as many threads as you want.
import java.awt.*;
import java.awt.event.*;
import java.applet.*;

class Ticker extends Thread {
  private Button b = new Button("Toggle");
  private TextField t = new TextField(10);
  private int count = 0;
  private boolean runFlag = true;
  public Ticker(Container c) {
  b.addActionListener(new ToggleL());
  Panel p = new Panel();
  p.add(t); p.add(b); c.add(p);
  }
  class ToggleL implements ActionListener {
  public void actionPerformed(ActionEvent e) {
  runFlag = !runFlag;
  }
  }
  public void run() {
  while (true) {
  if(runFlag)
    t.setText(Integer.toString(count++));
   try {
    sleep(100);
  } catch (InterruptedException e){}
  }
  }

CompteurPT:

  public void stp() {
  runFlag = false;
  }
  public void restart() {
  runFlag = true;
  }
}

public class CompteurPT extends Applet {
  private Button start = new Button("Start");
  private Button stop = new Button("Stop");
  private Button restart = new Button("Restart");
  private boolean started = false;
  private Ticker[] s;
  private boolean isApplet = true;
  private int size;
  public void init() {
  // Get parameter "size" from Web page:
  if(isApplet)
  size = Integer.parseInt(getParameter("size"));
  s = new Ticker[size];
  for(int i = 0; i < s.length; i++)
  s[i] = new Ticker(this);
  start.addActionListener(new StartL());
  add(start);
  stop.addActionListener(new StopL());
  add(stop);
  restart.addActionListener(new RestartL());
  add(restart);
  }
  class StartL implements ActionListener {
  public void actionPerformed(ActionEvent e) {
  if(!started) {
    started = true;
    for(int i = 0; i < s.length; i++) s[i].start();
  }
  }
  }
  class StopL implements ActionListener{
  public void actionPerformed(ActionEvent e) {
  for(int i=0;i<s.length;i++) s[i].stp();
  }
  }
  class RestartL implements ActionListener{
  public void actionPerformed(ActionEvent e){
  for(int i=0; i< s.length; i++) s[i].restart();
  }
  }
  public static void main(String[] args) {
  CompteurPT applet = new CompteurPT();
  // This isn't an applet, so set the flag and
  // produce the parameter values from args:
  applet.isApplet = false;
  applet.size = (args.length == 0 ? 5 :
           Integer.parseInt(args[0]));
  Frame aFrame = new Frame("CompteurPT");
  aFrame.addWindowListener(
  new WindowAdapter() {
    public void windowClosing(WindowEvent e) {
    System.exit(0);
    }
  });
  aFrame.add(applet, BorderLayout.CENTER);
  aFrame.setSize(200, applet.size * 50);
  applet.init();
  applet.start();
  aFrame.setVisible(true);
  }
}
 

Partage des resources
//: Sharing1.java
// Problems with resource sharing while threading
import java.awt.*;
import java.awt.event.*;
import java.applet.*;

class TwoCounter extends Thread {
  private boolean started = false;
  private TextField
  t1 = new TextField(5),
  t2 = new TextField(5);
  private Label l =
  new Label("count1 == count2");
  private int count1 = 0, count2 = 0;
  // Add the display components as a panel
  // to the given container:
  public TwoCounter(Container c) {
  Panel p = new Panel();
  p.add(t1);
  p.add(t2);
  p.add(l);
  c.add(p);
  }
  public void start() {
  if(!started) {
  started = true;
  super.start();
  }
  }
  public void run() {
  while (true) {
  t1.setText(Integer.toString(count1++));
  t2.setText(Integer.toString(count2++));
  try {
    sleep(500);
  } catch (InterruptedException e){}
  }
  }
  public void synchTest() {
  if(count1 != count2)
  l.setText("Unsynched");
  }
}

class Watcher extends Thread {
  private Sharing1 p;
  public Watcher(Sharing1 p) {
  this.p = p;
  start();
  }
  public void run() {
  while(true) {
  for(int i = 0; i < p.s.length; i++)
    p.s[i].synchTest();
  try {
    sleep(50);
  } catch (InterruptedException e){}
  }
  }
}

public class Sharing1 extends Applet {
  TwoCounter[] s;
  private Button
  start = new Button("Start");
  private boolean isApplet = true;
  private int numCounters = 0;
  private int numObservers = 0;
  public void init() {
  if(isApplet) {
  numCounters =
    Integer.parseInt(getParameter("size"));
  }
  s = new TwoCounter[numCounters];
  for(int i = 0; i < s.length; i++)
  s[i] = new TwoCounter(this);
  Panel p = new Panel();
  start.addActionListener(new StartL());
  p.add(start);
  add(p);

  new Watcher(this);
  }
  class StartL implements ActionListener {
  public void actionPerformed(ActionEvent e) {
  for(int i = 0; i < s.length; i++)
    s[i].start();
  }
  }
  public static void main(String[] args) {
  Sharing1 applet = new Sharing1();
  // This isn't an applet, so set the flag and
  // produce the parameter values from args:
  applet.isApplet = false;
  applet.numCounters =
  (args.length == 0 ? 5 :
    Integer.parseInt(args[0]));
  Frame aFrame = new Frame("Sharing1");
  aFrame.addWindowListener(
  new WindowAdapter() {
    public void windowClosing(WindowEvent e){
    System.exit(0);
    }
  });
  aFrame.add(applet, BorderLayout.CENTER);
  aFrame.setSize(300, applet.numCounters *100);
  applet.init();
  applet.start();
  aFrame.setVisible(true);
  }
} ///:~

page précédantetable des matières