Threads

Processes and threads

Multiprocessing - two or more programs that run "visibly" competitively under the control of the operating system. The programs have no connection with each other except the fact that they are started and run simultaneously.
It is implemented by the operating system and no measures need to be taken within the program.


 Multithreading - two or more tasks that are performed "visibly" in parallel within the same program. Sometimes called "lightweight" processes
Although it requires maintenance of the operating system, it is implemented and executed by the program itself. special program design and planning is required.


Features

Constructors

Thread()
          Allocates a new Thread object.
Thread(Runnable target)
          Allocates a new Thread object.
Thread(Runnable target, String name)
          Allocates a new Thread object.
Thread(String name)
          Allocates a new Thread object.


Some commonly used methods

public static Thread   currentThread()
          Returns a reference to the currently executing thread object.
 public final String     getName()
          Returns this thread's name.
public final void setName(String name)
          Changes the name of this thread to be equal to the argument name.



Creating

 

two methods for creating a Thread: 

   - 1) A class derivated from class.lang.Thread
             - Java.lang.Thread inherits Runnable
             - the run () method must be redefined
   - 2) A class inheriting the Runnable interface
             - the run () method must be defined

A class derivated from class.lang.Thread

class Proc1 extends Thread {
Proc1() {...} //
constructor
  ...
  public void run() {
    ... // 
thread activity
  }
}
...

Proc1 p1 = new Proc1();
// creating the thread p1
p1.start(); // Starting the thread and executing p1.run ()

A class inheriting the Runnable interface

class Proc2 implements Runnable {
Proc2() { ...} // 
constructor
...
public void run() {
... // 
thread activity
}
}
...

Proc2 p = new Proc2();
Thread p2 = new Thread( p);

...
p2.start(); // Starts a thread that executes p.run ()

Which method to choose?

o Method 1: Thread subclass
     - when the class does not inherit another class (note: there is no multiple inheritance)
     - for applications
o Method 2: Runnable inheritance
     - when the class is already derived
     - for applets

public class MyThreadApplet extends Applet implements Runnable {}

 

   

Thread States

The state of the thread shows what it is currently doing and what it is able to do. It can be in 4 states: New, Runnable, Blocked and Dead (Terminated).

 
 

For each entry into a blocked state, there is a specific and different way of returning to a runnable state. Each return only works for the respective way of entry. For example, if it is blocked with sleep (), the return can only take place after the specified number of milliseconds has elapsed. Calling the resume () method will have no effect.

Method isAlive()

The Thread class has an isAlive() method that is used to check the status of a thread::

Method getState()

Release 5.0 introduces the Thread.getState() method. When called, one of the following Thread.State values is returned:

 


    A simple example - a thread running all the time:

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

 public class CounterA extends JPanel 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);
        private Label  l = new Label("Thread: no Thread counter yet");
       public void init() {
              add(t);
              start.addActionListener(new StartL());
              add(start);
              onOff.addActionListener(new OnOffL());
              add(onOff);
              add(l);
         }
         public void run() {
                 while (true) {
                    try {
                        Thread.sleep(100);
                    } catch (InterruptedException e){}
                     if(runFlag) {
                          t.setText(Integer.toString(count++));
                          l.setText("Thread: "+selfThread.getName());
                     }
                 }
          }
 
    class StartL implements ActionListener {
        public void actionPerformed(ActionEvent e) {
                if(selfThread == null){
                        selfThread = new Thread(CounterA.this);
                        selfThread.start();
                }
                runFlag = true;
        }
  }
  class OnOffL implements ActionListener {
          public void actionPerformed(ActionEvent e) {
                  runFlag = false;
          }
  }
  public static void main(String[] args) {
          CounterA cnt = new CounterA();
          JFrame frame = new JFrame("CounterA");
          frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        
          frame.add(cnt);
          frame.setSize(300,200);
          cnt.init();
          frame.setVisible(true);
    }
}  


The thread is killed and re-created
//: CompteurA1.java
// Using the Runnable interface to turn the
// main class into a thread.
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;

public class CounterA1 extends JPanel implements Runnable {
    private int count = 0;
    private Thread selfThread = null;
    private Button    stop = new Button("Stop"),
    start = new Button("Start");
    private TextField t = new TextField(10);
    private Label  l = new Label("Thread: no Thread counter yet");
    private boolean runFlag=true;
    public void init() {
        add(t);
        add(l);
        start.addActionListener(new StartL());
        add(start);
        stop.addActionListener(new StopL());
        add(stop);
    }
    public void run() {
        while (runFlag) {
            try {
                Thread.sleep(100);
            } catch (InterruptedException e){}
            t.setText(Integer.toString(count++));
            l.setText("Thread: "+selfThread.getName());
        } 
        selfThread = null;
    }
    class StartL implements ActionListener {
         public void actionPerformed(ActionEvent e) {
             if(selfThread == null){
                 selfThread = new Thread(CounterA1.this);
                 runFlag=true;
                 selfThread.start();
             }
         }
    }
    class StopL implements ActionListener {
        public void actionPerformed(ActionEvent e) {
             if(selfThread != null) {
                //  selfThread.stop();     deprecated
                 runFlag =false;               
             }
       }
    }
    public static void main(String[] args) {
        CounterA1 cnt = new CounterA1();
        JFrame aFrame = new JFrame("CounterA1");
        aFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        aFrame.add(cnt);
        aFrame.setSize(300,200);
        cnt.init();
        aFrame.setVisible(true);
    }
}

 
 
 The same example with many threads:

 //: CounterPT.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 javax.swing.*;

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());
     JPanel p = new JPanel();
     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){}
    }
  }
  public void stp() {
    runFlag = false;
  }
  public void restart() {
     runFlag = true;
  }
}

public class CounterPT extends JPanel {
  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 int size;
  public void init() {     
     this.setLayout(new FlowLayout()); 
     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) {
      CounterPT cnt = new CounterPT();

      cnt.size = (args.length == 0 ? 5 : Integer.parseInt(args[0]));
      JFrame aFrame = new JFrame("CounterPT");
      aFrame.add(cnt);
      aFrame.setSize(200*(1+cnt.size/10), 500);
      aFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
      cnt.init();
      aFrame.setVisible(true);
  }
}

    

 Exercise: Change the program so that after reaching a certain value the thread completes its execution. Enter the "New" button to create new counter threads.