Interactive MultiThreading

Peter Komisar   
©    Conestoga College   
latest version  5.7 / 2010


Just to review, recall the following is one of the standard
ways to create and start a Java thread running. In this
example Thread class is extended. Runnable's run( )
method is overridden. The class is instantiated and
it's start( ) method is called.

Subclassing Thread Sample Code

 class BlueBird extends Thread{
       public void run( ){
         System.out.println("BlueBird ");
         }
    }

 class Birder{
      public static void main(String[]args){
        BlueBird blue = new BlueBird( );
        blue.start( );
        }

     }

We might also mention we looked at various methods of
stopping threads including throwing the InterruptedException.



More Details On Java Threads


Threads allow a program operating on an operating
system to execute separate activities concurrently. A
system thread is a sub-process of the operating system
that can be scheduled. Threads are important in many
server applications where thread resources can be
managed to supply services to many clients concurrently.


Java Uses Each Operating System's Unique Thread Model

Each operating system's thread implementation is different.

Before Java appeared , a programmer would usually need
to cater to the thread model used on the operating system
that he or she was working on.

Java supplies a generic thread model that is portable across
operating systems freeing the developer of needed to know
about the details of each operating systems thread model.

// Java's thread model is portable

As we discussed earlier, this does not imply that Java thread
behavior will be identical on every operating system. Cliff
Berg in his book, 'Advanced Java', brings some interesting
information to bare on these issues.


Java Thread Objects are Wrappers for Native Threads

Java implementations usually make use of the native
thread model. The Java thread object is an abstraction
that uses the native system thread implementation. Java
Thread class objects act as 'wrappers' for the native
threads of the operating system.

Details of the start( ) Method

When a Thread object is instantiated, the native thread
doesn't exist yet. Only the Java wrapper has been
allocated in memory. When the start( ) method is called,
a system thread is started and run. The start( ) method
acts as a bridge interfacing the Java object to native
thread sub process. The start( ) method provides the
data structure that connects the native system thread
to the Java thread object, and creates and runs the
native system thread.

Relationship Between Java Thread, start( ) & Native Thread

// Thread Wrapper is in memory, native thread doesn't exist yet // native system thread is started and run


Categories of Thread Interactions


Peter Linden in 'Just Java' provides a good classification
system for threads based on how they interact. The four
general categories
are described below.

Relationships between Threads

1) Unrelated Threads
2) Related but Unsynchronized
3) Related and Synchronized
4) Related, Synchronized and Cooperating
 

Unrelated Threads

We see threads that unrelated in use all the time when
we use computer programs.
Modern web browsers use
multithreading extensively. For instance while a news
clip
is being played in one frame, an application may be
running
in another process, perhaps a time display. At
the same time the browser might be negotiating a download
and
presentation of a new page in a new tab. A print job
could even be going on in the background.
These are all
unrelated but concurrently running threads.


Example

class Printer extends Thread {
public void run(){
System.out.println("Printer called");
try{
   Thread.sleep(5000);
   }
catch(InterruptedException ie)
   {
   ie.printStackTrace();
   }   
System.out.println("Print finished");
}
}   // a printer function
 
class WebBrowser extends Thread{  
public void run(){
System.out.println("Browser runs");
try{
   Thread.sleep(5000);
   }
catch(InterruptedException ie)
   {
   ie.printStackTrace();
   }   

System.out.println("Browser finished");

}
}   // a browser

class Calculator extends Thread{
public void run(){
System.out.println("Financial Calculator runs");
try{
   Thread.sleep(5000);
   }
catch(InterruptedException ie)
   {
   ie.printStackTrace();
   }   

System.out.println("Calculation complete");

}
  // a calculator
     
class MultiApp{
public static void main(String[]args){
   try{
    
      WebBrowser browser = new WebBrowser();
      Printer printer = new Printer();
      Calculator calc = new Calculator();
      
      // give them different start times
     
      Thread.sleep(700);
      browser.start();
      Thread.sleep(1100);
      printer.start();
       Thread.sleep(1300);
      calc.start();      
      Thread.sleep(1700);
      }
      catch(InterruptedException ie){ie.printStackTrace();}
      }
     }


Related but Unsynchronized

This category can be used to describe threads that are
cooperating on completing the
same task, however each
thread has a duty that they can completed independently
of
other threads. A parallel process where a number range
is split into a number of sub
-ranges where each sub-range
is searched by a separate thread fits this description.

Peter van der Linden, in his Java text, 'Just Java' has
a nice code sample that shows threads working in a
related but unsynchronized fashion. It is very concise as
well. A couple lines were added to handle the case where
a number has not been provided at the command line to
test if it is prime.

The way the program works, is if no factors are found
the program returns with no reports.


Peter van der Linden's TestRange Code
// 'Just Java', Sun Press

class testRange extends Thread{
  
   static long possPrime;
   long from, to; 
   // constructor
   // record the number we are to test, and
   // the range of factores we are to try
  
 testRange(int argFrom, long argpossPrime){
     possPrime = argpossPrime;
     if (argFrom==0) from=2; else from=argFrom;
     to = argFrom + 99;
     }
     public void run(){
       for(long i=from; i<=to && i<possPrime; i++){
           if (possPrime%i == 0) { // i divides possPrime exactly
      System.out.println(
      "factor " + i + " found by thread " + getName( ));
      this.stop ( );  // uses the evil stop( ) method  ed.
      }
    yield( );
    }
  }
}
   
public class testPrime{
 public static void main(String s[]){
   
    if (s.length<1){
    System.out.println("Enter a number to test if it is prime");
    return;
    }
   
    long possPrime = Long.parseLong(s[0]);
    int centuries =(int)(possPrime/100) + 1;
   
  for(int i=0;i<centuries;i++){
     new testRange(i*100, possPrime).start( );
    }
  }
}

// for example, 3242891 is prime


Related and Synchronized

Related and synchronized threads are interacting. Both
are accessing some shared
domain. Perhaps three server
threads have been created to serve clients concurrently

and these threads are all sharing data from the same
address space.

// threads working on same shared data

Imagine a thread accessing a data item at precisely the
same instance that another thread is in the process
of
changing that data item. There is a potential problem
of data being read incorrectly or worse, being lost or
corrupted.
As we will see, special care needs to be
taken when threads interactively share data.

Related, Synchronized and Cooperating

A higher order of interaction is still possible. This is the
situation where threads interact
by sharing the same
data but go further. Threads can communicate to each
other when
they are ready to process each other's data.
This is often described as the Producer
Consumer
model. This kind of communication can also be done
in Java using classes from the java.io
package
PipedInputStream and PipedOutputStream.

We talk about the latter two cases in the following
discussion where examples will be supplied.


Synchronization


Synchronization is the process where concurrent threads
are only permitted to access
shared data in turn, essentially,
in a queue. A lot of terms have been used to describe this

type of mechanism. For instance, P. Naughton stated in
'The Java Handbook',
"A monitor is an object which is
used as a mutually exclusive lock or mutex."


The Monitor Lock & Mutex

In a short line, three terms have been used, 'monitor', 'lock'
and 'mutex' all of which
relate to the idea of synchronization.
The term 'monitor' is used not in the sense
of something
visual rather in relation to it's root 'mono' meaning 'one'.
The 'lock' term
is used in common sense to indicate a
thread has a lock on a process. The lock implies
other
threads are locked out of using a section of data. The term
'mutex' is an abbreviation for
the words, 'mutually exclusive'
and again alludes to the idea of a 'one at a time' usage.

// mono => 'one', mutex==> mutually exclusive, lock => exclusive use


The Semaphore

Another term used in this context is 'semaphore'. You may
be surprised
to know that the semaphore is a real object,
a flag that was passed by railmen to the engineer of a
train.
It was used where trains that ran in both directions shared
a single section of track. The flag physically represented a
guarantee that they and only they had access to
the single
section of track.

Specialists have stricter definitions of these terms. The
following quote, found in Heller & Robert's
'The Java
Developers Handbook' offers a stricter definition of a
monitor.

"A Java class as a whole is not a monitor strictly speaking
 unless all it's non-private
methods are synchronized to
 protect all data accesses and all it's data methods are

 
marked as private."
                  
                                                                
From the same source comes the following regarding the
semaphore flag.

"Before the days of electronic communication, in places
where a single track was used
by trains in both directions,
the signal man would have a flag or semaphore. No train

was allowed on the track unless the driver held the flag
obtained from the signal man.
When the train passed off
the track, the driver returned the flag to the signal man." ...

"When a 1 or 0 is used to protect delicate data, the
mechanism is often called a binary
semaphore"


                      - "The Java Developer's Handbook" - Heller & Roberts
 

The semaphore mechanism is built into Java's Object
class. Cooperation between synchronized objects is
also made possible by Object class methods wait( ),
notify( ) and notifyAll( ).
 

Guarded & Concurrent Reentrancy

Reentrant code is called 'thread safe' code and describes
code that can be executed safely by many threads at the
same time without any extra provisions for protecting data.

Cliff Berg in 'Advanced Java' helps outline two forms of
reentrant code, 'guarded' and 'concurrent' that brings us
into conformity with the Object Management Group's UML
language definitions for these terms.

Concurrent Reentrant Code

Concurrent reentrant code is naturally thread-safe by
virtue of how it has been written in Java and does not
use any explicit internal mechanism that sends threads
into the wait state to achieve concurrency.

This boils down to avoiding the use of static and instance
variables in methods or scoped sections of code unless
these variables are defined as constants. In other words,
use local method variables that have the same life span
as the method call itself.

// avoid static variables and instance variables defined in
// class scope unless these variables are constants

Instance and static variables may both outlive the life cycle
of a section of code making them vulnerable to another
threads access. Concurrent reentrant code is based on the
use of local variables that will disappear at the same time
the method code completes.

// concurrent reentrant code use local variables whose life span
// is the same as that of the code section it is in

Guarded Reentrant Code  // 'code marked synchronized'

Guarded reentrant code introduces the 'explicit internal
mechanism' mentioned in the previous paragraph. In Java
this comes
down to using the 'synchronized' keyword. The
synchronized keyword works
through a mechanism that
translates to VM instructions at the Virtual Machine
level.
The VM level instructions are used to allow or restrict
access to
synchronized code depending if that code is
being used by another thread or
not.

// guarded re-entrant code uses the 'synchronized' keyword, and
// works at the VM level


The 'synchronized' keyword

The synchronized keyword can be applied to static or
non-static methods or to
blocks of code. When applied
to a block of code, a 'synchronized
block' is created.

Because the 'synchronized' keyword is not considered
part of a method's signature, it can be overridden so
subclass versions of the synchronized methods do not
need to be synchronized.

// the 'synchronized' keyword may be applied to
// 'synchronized' blocks static and non-static methods


Atomic Processes

Synchronization makes a process 'uninterruptable' or
'atomic'. Some processes are atomic naturally such as
the assignment of an int value. Assigning a long value
is not however atomic. An interrupt could potentially stop
a thread before a long assignment completed.

The synchronized keyword can be used to ensure a section
of code will finish before being interrupted by another thread.
This is particularly important in transaction processing.

// synchronization makes a process 'atomic' or uninterruptable


Early Synchronization Costs Have Been Cut

Cliff Berg reports that early versions of synchronization
in Java were expensive in terms of performance, being
almost 10 times slower than comparable non-synchronized
code. Fortunately, in newer versions of Java, the process
of synchronization is only moderately slower than regular
Java methods.

// performance of synchronized methods has greatly improved 


Pre-empted Synchronized Code Retain it's Lock

Synchronized code also can be pre-empted in the normal
course of thread scheduling activity. Java's model is
designed to let low priority threads get some time even
if high priority threads are running. When pre-empted, a
synchronized section of code retains it's lock. No other
thread will execute the code while the suspension of
activity is occurring.

Synchronization is also used extensively in Java library
code. Vector uses synchronized methods.

// a preempted thread retains it's lock on a synchronized section  of code



Synchronizing Java Code


The 'synchronized' keyword is simple to add. The first
case we look at adds
the synchronized keyword to a
section or scope of code. Because of the performance

costs associated with synchronization, keeping a section
of code that is synchronized as short as possible will
keep the
performance premium down. 


Synchronizing a Block of Code

Following is an example of a synchronized block of code.
A synchronized block
is a parenthesized code block
prefixed with synchronized( target ) where target is
an
arbitrary class instance. This works as every root class
descendant inherits
Object class' mechanism to queue
or 'single file' calling threads.


Parts of a Synchronized Block

synchronized (target_object)
          {
        
/* perhaps a subset of a method's code*/ 
          }


Following is an synchronized block from a CORBA
code example.


Example of a Synchronized Block

 java.lang.Object sync = new java.lang.Object( );
     synchronized (sync) {
     sync.wait( );
     }

 

Synchronizing on an Non-Static or Instance Method

Synchronizing non-static methods provides a means to make
'thread-safe' accesses to instance variables. With a non-static,
synchronized method the implied object that is used for
synchronization is 'this', the instance object. As a result, each
method is synchronized to it's container.
This type of lock is
called an 'object lock'. Note other non-synchronized methods
and static methods of this class are not effected by this lock.

// 'object lock' is a lock on an instance

It should be pointed out that other objects of the same class
have no relationship
to each other in terms of concurrency.
Each object is only synchronized to itself. The moment
the
synchronized keyword is added a lock based on the class
object is created.

// synchronizing instance methods provides thread safety within the object

Non-Static Method Example

           class Sync{
                  int [ ] key = new int[ 8 ]; 
                  synchronized void setKey(int i, int value){
                       key[i]=value;
                       }
                  synchronized int[] getKey( ){
                       return key;
                       }
                   }

The instance variables can work on a static variable
as is shown in the following example.

Example

class Synch2{
                 static int key;
                  synchronized void setKey(int value){
                       key=value;
                       }
                  synchronized int getKey( ){
                       return key;
                       }
   public static void main(String [] args){
               Synch2 sync=new Synch2();
               sync.setKey(6);
               System.out.println(sync.getKey());            
                }
          }

How is it Useful to Synchronize Object Methods

If many objects used the same instance simultaneously
the data being targeted would be thread safe and
protected from corruption.  The instance when used will
behave with thread-safe integrity.
 
// consider several threads use the same instance of a calculator
// class. The methods will not interrupt until completing
inside this
// multi-threaded environment

Synchronizing on a Static or Class Method

Synchronizing on a static method is similar in procedure to
adding synchronization
to an instance method. Instead of
the class object being the element that supplies
the lock,
the class itself supplies the mutex. This is called a 'class
lock'.

Static Method Example

class Sync{
         static int [ ] key = new int[ 8 ];
        
static synchronized void setKey(int i, int value){
           key[i]=value;
           }
         static synchronized int[] getKey( ){
           return key;
           }
         }


Form Equivalent to a Synchronized method

We can synchronize a section of code by putting it in a
synchronized block inside
a method. If this block occupied
the entire scope of the method it would be the same
as the
second notation form that is the common form found in the
Java libraries.

 

Form A             void method( ){
                          synchronized (this){
                           //...
                          }
                     }

// is the same as

Form B           synchronized void method{
                                        //...
                                 }



Race Condition
  // coordination of thread activity is lost

Race condition occurs when more than one thread is
able to act on shared data
at the same time before some
condition limiting their activity is able to be invoked.
There
are a couple of ways to protect against race condition.

First is to use synchronized code so one threads actions
are complete before the next begins. The other technique
involves making
shared items static. Making the variables
class variables
ensures there is only one item being
effected by concurrent threads, such as in an increment
operation.

// protection: make shared data synchronized & static
 

Deadlock

Intuitively we know the feeling of deadlock when the
computer 'locks up' or we are stuck in a traffic
jam,
especially the sort where vehicles are blocking
each
other from moving at an intersection of two
lanes.

Synchronization can lead to this special condition, known
as 'deadlock'. The condition is
also called 'starvation' or
'deadly embrace'. Deadlock describes the situation where

neither of two threads can proceed because the other holds
the lock that it needs.
Because neither can proceed, neither
can leave the synchronized block they are in
and as a result,
neither can relinquish the lock the other thread needs.

All deadlock conditions are based on design errors.
Deadlock can be avoided by following a
same sequence
for obtaining the locks and avoiding 'mirror' symmetries
that result
in paradoxical deadlock scenarios.

 Example of an Orchestrated Deadlock 
 
Thread 1       Process to Deadlock  Thread 2 
 run( ){
 synchronized
  (ObjectA){
  sleep(500); 
  ObjectB.methodB( ); 
  } 
}
Thread 1 obtains lock on ObjectA and goes to sleep allowing Thread 2 to start and obtain the lock on ObjectB and then also go to sleep. Thread 1 regains control and calls the method on Object B but B is under the lock of Thread 2.  Thread 2 wakes and attempts to call ObjectA's method but it is under the lock of Thread one and is also inaccessible. Now the
threads are in
a deadlock or deadly embrace. 
 run( ){
 synchronized
 (ObjectB){
 sleep(500);
 ObjectA.methodA( ); 
 }
}
  ObjectA 
  methodA( )

 ObjectB
 methodB( )

The Internet supplies Java deadlock examples. The Java
programmers really has to make an effort to reliably create
the 'deadlock' condition. The examples are long so the links
are listed rather than the code. The 'deadly embrace' pattern
is more discernible in the second of the following examples.

Java Deadlock Examples

http://java.sun.com/docs/books/faq/src/thr/DeadlockExample.java
http://www.java2s.com/Code/Java/Threads/Deadlock.htm

The following example is from the java2s site and is quite
'deadly' in that it is so short yet quick to lock. This code uses
inlined creations of Thread objects. The classic pattern is
in it as the first thread locks on synchronized resource 1
 and defines resource 2.  Symmetrically,  Thread 2 locks on
resource 2 and defines resource 1.

DeadLock Example  // from the java2 site

// http://www.java2s.com/Code/Java/Threads/Anotherdeadlockdemo.htm

public class AnotherDeadLock {
  public static void main(String[] args) {
    final Object resource1 = "resource1";
    final Object resource2 = "resource2";
    // t1 tries to lock resource1 then resource2
    Thread t1 = new Thread( ) {
      public void run() {
        // Lock resource 1
        synchronized (resource1) {
          System.out.println("Thread 1: locked resource 1");

          try {
            Thread.sleep(50);
          } catch (InterruptedException e) {
          }

          synchronized (resource2) {
            System.out.println("Thread 1: locked resource 2");
          }
        }
      }
    };

    // t2 tries to lock resource2 then resource1
    Thread t2 = new Thread() {
      public void run( ) {
        synchronized (resource2) {
          System.out.println("Thread 2: locked resource 2");

          try {
            Thread.sleep(50);
          } catch (InterruptedException e) {
          }

          synchronized (resource1) {
            System.out.println("Thread 2: locked resource 1");
          }
        }
      }
    };

    // If all goes as planned, deadlock will occur,
    // and the program will never exit.
    t1.start();
    t2.start();
  }
}
         


Thread Cooperation


Threads that are Related, Synchronized and Cooperating

The method's of the object class wait(), notify( ) & notifyAll( )
can be used to allow
threads to communicate making their
operation more efficient. This is useful in the
circumstance
where there is no point in a thread running unless another
thread has
finished it's task.

Object Class Thread Methods

wait( ) - The wait( ) method is called by a thread object
to release itself from the object that
is the monitor and
return to the wait state. The object has made itself
inactive and is waiting to be
notified of some condition
by another thread.

// makes itself wait

notify( ) - The notify( ) method is used by a thread to
notify( ) some other thread that
a particular condition
has become true and that the other thread should come
out of the
wait state and once again seek control of the
monitor.

// notifies one

notifyAll( ) - The notifyAll( ) method is like notify( ) except
that it notifies all the
waiting thread that some condition is
true.

The three methods of the Object class can be used to
create what is referred to as the 'Producer Consumer'
model where a producer generates some condition such
as information being available, notifies a waiting thread
that the material is available to be consumed.
 

Producer Consumer Model in a Word Example
 
 A Post Office Analogy of the Producer Consumer Model  // if you have the time.

 Circumstances may exist where a thread seeks and gains the  CPU to check a condition. The condition hasn't changed so CPU  time was wasted in the process. Carry this thought into an analogy of a citizen checking the post office for the arrival of a parcel. But  rather than having time wasted with unsuccessful checks, the postman  suggests the customer wait and be notified when the parcel arrives.  In this analogy, the post office is the program in which threads (people) are queued (synchronized) for service. (Only one person  has the postman's attention at one time). When the postman (the  CPU) checks for your parcel, he see's if it is in. (The act of  'checking' is the role of a synchronized method. Whether the parcel  is in or not describes a boolean condition used to tell the thread to  wait or to be notified, in the analogy, whether the person should  come back to the post office.) The person waiting is analogous to  a thread being blocked.

 The object being used to synchronize 'keeps' it's threads in a  'waiting pool'. When the condition changes (i.e.the parcel arrives  and boolean is switched to true) the object can notify the waiting  threads to return to the ready state to contend for the CPU. Note if
all the threads in the waiting pool are waiting
for the same condition to change, (return to the analogy, "the tax returns are in") the object  can notifyAll( ) threads to return to the ready state.

 The producing side of the equation can also participate  in this  analogy. Mail delivery vehicles arriving at the post office can  participate in 'calling' (methods) from the post office to dispatch  the notification that the wait for a parcel can be discontinued.  Meanwhile other operations at the post office (representing static  synchronized methods and non-synchronized methods) would  carry on independently, business as usual.


Producer Consumer Code Sample

One example where the producer consumer model is useful
is the act of loading and
firing a cannon. If the loading of the
charge and the cannon ball is not finished, there is
no point
in the one who fires the cannon to put flame to the cannon's
wick. (This is an
old time cannon.) 

Similarly, there is no point in the loader trying to reload a
cannon if
it hasn't been fired. The wait( ) and notify( ) methods
are used to communicate this
information in the following code
example.

// Class Cannon has just two members, the load and fire methods.

class Cannon{

// the synchronized load method
 synchronized boolean load(boolean loaded){
  while(loaded == true){
    try{
        wait( );                 
 // wait( ) method from the Object class

        }
    catch(InterruptedException e){ }
  }

  loaded=true;
  System.out.println
 (Thread.currentThread().getName() + ": loaded ");

       notify( );                  
// notify( ) method from the Object class

  return loaded;
  }

// the synchronized fire  method
synchronized boolean fire(boolean loaded){

  while(loaded == false){
  try{
     wait( );                      
// wait( ) method from the Object class

     }
     catch( InterruptedException e){ }
  }

  loaded=true;
  System.out.println(Thread.currentThread().getName() +": fired ");
  loaded=false;
  notify( );                      
// notify( ) method from the Object class

  return loaded;
  }
}

/* The Gunners class extends Thread and provides the necessary
  run method( ). It also creates
three instances of itself. These new
  threads will be invoking the run( ) method once they
are started. In
  the run method an instance of the Cannon class is created  to provide
  the
synchronized load and fire methods. When  methods are declared
  synchronized they are
implicitly synchronized on this, the containing
  class instance.

*/

class Gunners extends Thread {
Gunners(String s){
super(s);
}
  static int i=0;
  boolean loaded = false;
  public static void main(String args[]){

     Gunners g1=new Gunners("A. Left" );
     Gunners g2=new Gunners("B.                             Right" );
     Gunners g3=new Gunners("C.              Center");

    g1.start( );
    g2.start( );
    g3.start( );
    }

   public void run( ){

    for(int i=0; i<3;i++){
       Cannon m=new Cannon( );
        boolean b =false;
        b=m.load(b);
        b=m.fire(b);
        try{Thread.currentThread().sleep             // delays of war
        (500);}catch(InterruptedException ie){ }
      }
   }
}


Piped Streams

While wanting to maintain the focus on Threads it should
be pointed out that the consumer producer model can be
emulated using classes from the java.io package. Piped
streams can communicate data to each other directly
using PipedInput
and PipedOutputStream. They do this by
virtue or a shared buffer in memory. A PipedOutputStream
can be opened on
a PipedInputStream or visa versa.


Example

PipedInputStream in=new PipedInputStream( );
PipedOutputSteam out=new PipedOutputSteam( in);

// notice pipes are different. An 'out' opens on an 'in'

Inside the Consumer code below a PipedInputStream is
opened on the PipedOutputStream object that is created
in the Producer.

The following example is from Peter Van der Linden's
text 'Just Java'. It should be noted that on a relatively
late version of Linux (Mandrake Linux 10.0) a lot more
bananas are being produced than consumed. The 'mod
20' was added to make the producer less zealous on
faster machines.

'Mod' ification

  return ( (System.currentTimeMillis() - start) % 20);


Sample showing the Consumer Producer Pattern Using Pipes 
// from Peter Van der Linden's text 'Just Java', Sun Press

import java.io.*;

public class expipes{
public static void main(String args[]){
  Producer p = new Producer( );
  p.start();
 
  Consumer c = new Consumer(p);
  c.start( );
  }
}

class Producer extends Thread{
  protected PipedOutputStream po = new PipedOutputStream();
  private  DataOutputStream dos = new DataOutputStream(po);
 
  public void run( ){
    // just keep producing numbers that represent the
    // amount of millisecs program has been running
    for(;;) produce( );
    }
   
    private final long start = System.currentTimeMillis( );
   
    private final long banana(){
       return ( (System.currentTimeMillis( ) - start) % 20);
       }
 
       void produce( ){
         long t = banana();
     System.out.println("produced " + t);
     try{ dos.writeLong(t);}
     catch (IOException ie){System.out.println(ie);}
     }
     }
    
 // This class consumes everything sent over the pipe.
 // The pipe does the synchronization. When the pipe
// is full,
this thread's read from the pipe is blocked
 
 class Consumer extends Thread{
 private PipedInputStream pip;
 private DataInputStream d;
 
 // java constructor idiom, save argument
 
 Consumer(Producer who){
   try{
      pip = new PipedInputStream(who.po);
      d = new DataInputStream(pip);
      } catch(IOException ie){
         System.out.println(ie);
     }
      }
      long get(){
      long i=0;
      try{ i=d.readLong( ); // read from pipe
      } catch(IOException ie){System.out.println(ie);}
      return i;
      }
     
   public void run(){
         java.util.Random r = new java.util.Random();
     for(;;){
      long result = get();
      System.out.println("consumed: " + result);
      // next lines are just to make things asynchronous
      int randomtime = r.nextInt( ) % 1250;
      try {sleep(randomtime);} catch(Exception e){}
      }
     }
    }     



Multithreaded Servers


Multithreading is used frequently in server programs. By
providing a separate
thread process to each client a server
is able to handle several clients at the
same time. The
simplest approach is to spawn a new thread to service
each
client that presents itself to the server. This may
create a problem if too many
threads are spawn and
system resources begin to be seriously drained.

One approach to correct for this is to create a program that
limits the number of
threads that are spawned and have
them provide client services. Another
popular approach
is to use a mechanism called 'thread pooling' where thread
objects are
maintained in a thread pool and can be issued
to different object references as required.
To characterize
a multithreaded server we will first create a skeleton for
the
code.

Example of A Simple Multithreaded Server Skeleton

The Simple Multithreaded server creates a Thread subclass
whose run( )
method does all the server stuff. In this version
the constructor is designed
to use the socket object that is
generated by the ServerSocket's accept( )
method.

Sample of a Server Skeleton Creating a Thread per Service Call

import java.net.*;
import java.io.*;

class ServiceThread extends Thread{
         Socket socket;
         ServiceThread( Socket s ){
            this.socket=s;
            // other stuff
              }
           public void run( ){
              // use the socket and provide the network service
             }
         }

class Server{
        public static void main( String[] args){
             System.out.println
             ("Ready if we had a client and response code!");
             ServerSocket serverSocket=null;
            new Server( );
            try{
              serverSocket=new ServerSocket(9999);
            for ( ; ; ) {
                 Socket socket=null;
                 socket=serverSocket.accept( );
                 // blocks until a request is made
                 ServiceThread service=new ServiceThread(socket);
                 service.start( );
                 }
               }
               catch(IOException io){  }
              }
         }

This method might be OK if the service call is short
and the new Server threads are extinguished quickly.

Multithreaded Server with Limited Service Threads

Too many threads may represent a form of 'memory leak'
as thread resources
may not be considered entirely collectible
by the garbage collector. The next
example shows a server
that creates a limited number of threads.
 
This example of a server with limited service threads, is
taken from Heller & Robert's 'Java Developer's Handbook,
published by Sybex. The key feature in this to notice is the
Thread constructor used for each of the threads takes the
Server itself as the Runnable object, followed by names
we are giving to each thread.

Sample of a Server Utilizing a Limited Number of Threads

// MultiServe.java exampled in the 'Java Developer's
// Handbook'
' by Heller & Roberts published by Sybex
   
import java.net.*;
import java.io.*;
import java.util.*;

public class MultiServe implements Runnable{
private ServerSocket ss;

public static void main(String args[]) throws Exception{
MultiServe m = new MultiServe();
m.go();
}

public void go() throws Exception{
// socket set to an arbitrary port ed.
 ss = new ServerSocket(1313, 5);
   Thread t1 = new Thread(this, "1");
   Thread t2 = new Thread(this, "2");
   Thread t3 = new Thread(this, "3");
   t1.start( );
   t2.start( );
   t3.start( );
   }
   
   public void run(){
     Socket s= null;
     BufferedWriter out = null;
     String myname = Thread.currentThread().getName();
     
     for(;;){
     try{
       System.out.println("thread " + myname +
            " about to accept..");
    s= ss.accept( );
    System.out.println("tread " + myname +
    " accepted a connection");
    out = new BufferedWriter(
        new OutputStreamWriter(s.getOutputStream()));
    out.write(myname + " " + new Date());
    Thread.sleep(10000);
    out.write("\n");
    out.close();
    }
    catch(Exception e){
    e.printStackTrace();
    }
      }
    }
  }        

This is a nice model. Where the first approach used one
loop that was serviced
by any number of service threads,
in this case the server functions are provided
entirely in
parallel by three separate threads each with their own
listening loop.


To Run You Need To Add a Client

Notice to use the above code you will have need to add
functionality and write your own clients. 


A Brief Note of Thread Pools

Many applications are transaction-oriented where perhaps
1000s of very short sessions are required. The overhead of
making client server connections in this scenario is very high.
An alternative is to use a Thread Pool. Thread pools are
commonly used in database management systems, CORBA
and Enterprise JavaBeans.

Cliff Berg outlines a Thread Pool based on the Consumer
Producer Model. In this scenario the Producer is the main
server object. A fixed pool of thread objects are created and
put into the wait state. On each client request, a service object
is created, put into a queue and notify( ) is called. One of the
threads in the pool will resume and attempt to obtain the
service object from the queue. If it succeeds it processes
the object. If it fails it goes back to the wait state with the
other threads in the pool.

// pool of fish waiting for the bait


Using Threads In Animations

The run method can be used in conjunction with a call the
Thread's sleep method and a loop that increments a counter
to control an animation. In the following code a line is drawn
in successive stages under the control of the run( ) method. 
Because the Color constructor's argument's  finally goes out
of range at a high value of the variable i, we have used the
exception thrown to throw a flag to terminate the drawing loop.

Animation Example Using Run as a Frequency Controller

import javax.swing.*;

import java.awt.*;


public class Animation {
        JFrame jf;
        PaintPanel pp;
     
        Animation(){   
        jf = new JFrame();
        pp= new PaintPanel();
        jf.getContentPane().add(pp);
        jf.setSize(600,600);
        jf.setVisible(true);
       
        Thread t=new Thread(pp);
        t.start();
        }

       
 public static void main(String[] args){
    new Animation();
}
}


class PaintPanel extends JPanel implements Runnable{
        int i=0;
        boolean flag=true;
       
    public void paint(Graphics g){
        try{
        g.setColor(new Color(i,i+i,255-i));
        g.drawLine(260-(i*2),220+(i*2),330+(i*2),280-(i*2));
        }
        catch(IllegalArgumentException iae){
            System.out.println
            ("Out of number range for the Color Constructor");
            flag=false;
           //  System.exit(0);  // could use System.exit( 0 ) alone
            }
     }
       
       
       
   
    /* (non-Javadoc)
     * @see java.lang.Runnable#run()
     */
    public void run(){
        try{
            while (flag){
            Thread.sleep(100);
            i++;
             repaint();
            }
        }
        catch(InterruptedException ie){}
       
        }
    }

   
   


Self Test                                      Self Test With Answers


1) Which of the following statements is not correct?

a) Threads allow several concurrent activities to occur by spawning new processes.
b) A system thread is a schedulable sub-process.
c) Each operating system's thread implementation is different.
d) Java supplies a generic thread model that is portable across operating systems

2) Consider two threads. One is generating a number that will be used by the
     second thread. The first thread will block until the second thread which is
     generating the number notifies it that the number is ready. Which of the
     following best describes the thread interactions.

a) Unrelated Threads
b) Related but Unsynchronized
c) Related and Synchronized
d) Related, Synchronized and Cooperating
 

3) All the following terms were used to describe the synchronization process.
Which one is an abbreviation for two other words?

a) monitor
b) semaphore
c) mutex
d) lock

4) [True or False] Concurrent reentrant code maintains concurrency by
not using variables that are defined locally.

5)  Which of the following statements is not correct?

a) The synchronized keyword can be applied to a block of code
b) a synchronized section cannot be put inside a non-synchronized method
c) In a synchronized block the object that supplies the monitor is placed
in round brackets between the synchronized keyword and the block that
is being synchronized.
d) The synchronized keyword effectively makes a section of code atomic.
 

6) Which of the following is not an Object class method used by synchronized
threads to communicate.
a) wait( )
b) waitAll( )
c) notify( )
d) notifyAll( )


Exercise



To practice getting familiar with the Producer Consumer Model
Modify the Gunner code to represent a different pair of activities.
Cook and serve burgers comes to mind. Anything that has a first
part that has to complete before the second will do. You may mimic
the code closely but should rename class and methods as
appropriate.  Increase the threads involved to 6 from 3.

Optional

And / Or Implement the above using piped streams.



1) Finish the 'Multithreaded Server with Limited Service Threads'
to supply a time in a distant country to a client. You need to supply
the client as well.