Multithreading Overview
Peter Komisar   ©  
Conestoga College   version  5.7  /  2010


Related Terms and Uses



Multiprogramming

Mainframes were designed to allow several users to use
the computer at the same
time. Each user's process has
it's own memory area or address space to
hold data and
instructions. The central processor does computations for
short intervals on each user's program in sequence. This
provides the illusion that several
things are being done at
the same. This process is also called 'multiprogramming'
.
The terms 'time sharing', 'multitasking' and 'multithreading'
have also used.

Multitasking

Today 'multitasking' is normally used to describe the low-
level creation of separate processes
on an operating
system with the attendant divisions of memory. An example
of multitasking the scenario where several DOS
sessions
are run simultaneously on the same machine. 

// multi-tasking - running several simultaneous 'heavyweight' DOS processes


The Platform

A 'platform' is often thought of as an operating system
used in combination with a hardware system. For example
Linux running
on an Intel processor is a computer platform.

When a computer sets up a new process, there are a lot
of demands made on system resources. As well, there is
a good deal of processing involved in switching
between
the different 'contexts' associated with each of the processes
that are running. For these reasons, mutltitasking is referred
to as a 'heavyweight'
process. Multitasking is also called
'timesharing' as each process will run in turn
for a few
milliseconds at a time.

// sometimes called timesharing


History of Multithreading

Multithreading is now reserved to describe the process
where many threads of activity are created within
a single
multitasking process. Multithreading is a newer phenomena
than multitasking
and came out of experimentation that
went on in the seventies. A thread API
standard for POSIX,
( the IEEE's Portable Operating System
Interface for UNIX)
was described in 1995.

// multithreading, several threads within a single process
// more recent development, IEEE describe POSIX in 1995

In the same year, 1995, Java was released with support
for multi-threading built in. James Gosling gives credit for
the ideas behind his Java thread model to the
early work
done by C.A.R. Hoare and also to the implementation of
threads that was
provided in the Cedar and Mesa languages
developed at Xerox PARC.

// Multithreading uses the resources of a single process
// and has little context switching costs

Because in multithreading multiple activities are occurring
within a process. The demand on system resources is that
of a single process. There is little overhead associated with
context switching within the program. Multithreading, then
is referred to as
a 'lightweight' process. When we discuss
multithreading in Java we are talking about
creating many
lightweight threads of activity within the same process

 

Multithreading Uses

One of the key advantages to multithreading is it allows
several things to occur in
a user's program at the same
time. For instance, a download that is managed in a 

separate thread will not interfere with a graphical user
interface's continued operation.
Music can be playing in
the background in another thread while the GUI remains

responsive and the download is going on. 

// several independent events can occur concurrently


Parallel Processing     

Multithreading threading is also useful to solve problems
that can better be done by
dividing the labor into parallel
processes. Consider a hypothetical phone directory that

has entries for all the people in North America. An old
algorithm called 'divide and
conquer' involves testing if
a name is in the upper or lower half of the book. Then
the
process is repeated on each subsection until the
name was found. The benefit of the algorithm is that at
each turn the size of the list being checked is halved.

If the phone book is huge traversing the list might take
a while. Another approach might be to
divide the book
into perhaps a hundred divisions and have each thread
divide and
conquer or just 'brute force' it's subsection.

// parallel processes can subdivide a problem and work
// on sections of it in tandem


Multithreading Well Suited to some Application Designs

Another use for multithreading is that some programs are
easier to write and implement
using threads. An example
of this is a server program. Having a server spawn a new

thread for each connection allows it to deal with several
clients simultaneously. It should
be said  that spawning too
many threads starts to have a negative impact as switching
contexts, even within a single process starts to take it's toll
on
system performance.

// some applications are easier to create using multithreading
 

Java Threads

We can give the first word on what Java threads are to the
inventor of Java,
James Gosling. His comments are quoted
below. 


" Java's threads are pre-emptive, and depending on platform
on which the Java
interpreter executes, threads can also be time-
sliced. On systems that don't support time-slicing, once a
thread
has started, the only way it will relinquish
control of the processor
is if another thread of a higher priority takes control of the processor.

If your applications are likely to be compute-intensive, you might
consider how to give up control periodically
by using the yield( )
method to give other threads a chance to
run; doing so will ensure
better interactive
response for graphical applications."  

- 'The Java Language Environment'  
                                           - James Gosling & Henry McGilton 

   http://java.sun.com/docs/white/langenv/index.html
 

Don't Tie Up the AWT Thread

Event handling and painting are handled by the AWT thread.
In short, if something in
an action method is going to take a
long time, (a long calculation), spin off a new thread
to do it
to free up the event handling ability of the AWT thread. Also
in this regard it is
recommended not to create new GUI
components in new threads spun off from within
action
methods as this will may lead to synchronization problems.

// if a thread is 'spun' from an action method, creating a GUI
// in this thread could create synchronization problems


Thread Scheduling



Preemptive and Time-Sliced Scheduling

When a Thread object's start( ) method is called a thread
of execution begins. Calling
start( ) registers the thread
with the 'thread scheduler' making the thread eligible to

run on the 'Central Processing Unit' or  CPU. The thread
may then enter a competition with other threads for
CPU
time.

Thread Mechanics

There are different models which are used to schedule
thread activity. The two most popularly implemented
models are 'preemptive' and 'time-sliced'.

Preemptive multithreading assigns each thread a priority and
threads with higher priority preempt threads with lower priority
with access to the CPU. The preemptive model affords some
predictability with respect to which processes will be allowed
more access to the CPU.

'Time-sliced' scheduling is also called 'round-robin' scheduling
and divides the time evenly between the different threads that
have been started. Each thread has equal time with the CPU.
Round-robin scheduling guards against one thread monopolizing
the central processors time.
 

Don't Count on Scheduling Behavior To Get
Predictable Results

Java schedules preemptively, however this behavior is
superimposed on the type
of scheduling that is incorporated
in the system that the JVM is running on. On platforms that use
round robin scheduling, the result may be a kind of hybrid
of
preemptive and round-robin behavior.

// Java's model is superimposed on whatever model the operating system uses.


Because the Java thread model needs
is based on the
underlying thread model of the operating system, behavior

may vary if a multithreaded application is ported across
several platforms.

Accordingly it is not recommended that you lean heavily
on scheduling behavior to derive any
kind of strictly
predictable coding results.

 

Java Thread Priority Constants

Java threads have priorities assigned to them. By default
priority is set to an int value of
5. This value is represented
by the constant, NORM_PRIORITYMAX_PRIORITY is
10, and
MIN_PRIORITY is 1. The Thread class has set
and get methods to set priority
or learn what the priority
is for a given thread.


Example
 

t1.setPriority( t1.getPriority( ) +1 );   

// increments a thread's priority by one  

ThreadGroup Class

Threads can be grouped into sets so they can be called
on a single method invocation.
Thread grouping provides
a mechanism to coordinate thread activity. A thread group

can also include other thread groups forming a tree where
every thread group except
the initial thread group has a
parent. A thread can access information about its own

thread group, but not it's thread group's parent thread
group or any other thread
groups. The class has a version
of interrupt( ) to stop all the threads in a group
at once.

Example  

ThreadGroup tg = Thread.currentThread( ).getTheadGroup( );


The following example demonstrate demonstrates how
ThreadGroup's interrupt( ) method can be used to stop
a group of threads. For now ignore other features of the
thread which we are very close to explaining later in the
note.

ThreadGroup Example

public class TGroup{
static int count;
public static void main(String[]args){


ThreadGroup tg1 =new ThreadGroup("GroupOne");

Team t1 = new Team(tg1,"Chicago");
Team t2 = new Team(tg1,"New York");
Team t3 = new Team(tg1,"Boston");

ThreadGroup tg2 =new ThreadGroup("GroupTwo");

Team t4 = new Team(tg2,"Montreal");
Team t5 = new Team(tg2,"Toronto");
Team t6 = new Team(tg2,"Detroit");


t1.start( );
t2.start( );
t3.start( );

t4.start( );
t5.start( );
t6.start( );
}
}

class Team extends Thread{
     ThreadGroup tg;
     String name;
      Team(ThreadGroup tg,String name){

      super(tg,name);
      this.name=name;
      this.tg = tg;
      }

// what a thread does is in it's run( ) method
// here it counts and sleeps until the limit is reached

public void run( ){
  
   try
     {
     while(true)
        {
        System.out.println(name);
        TGroup.count = TGroup.count + 1;
        System.out.println("Game Count: " + TGroup.count);
        Thread.sleep((long)( Math.random( ) * 5000 + 1));
     if (TGroup.count>20){
          tg.interrupt( );
      }
    } 
  }  
     catch(InterruptedException ie)
     {
     System.out.println(name + ": Our group has been interrupted!");
     }
   }
 }
 

How many Thread?

Each thread has a default stack size of 400K. Peter Van
der Linden in his text 'Just
Java' reported using a 32-bit
Unix machine with 2GB user address space was able
to
create 2000 'do nothing' threads on the machine before
it quit.

// coexisting threads taking up CPU time and memory space




Thread States



The Running State
      // in control

Threads exist in a number of states during their life cycle.
First there is the 'running state'. This is the condition where
a thread has control of the central processing unit. Then
there are a variety of 'wait states'. A number of thread
methods cause a thread to go into the wait state. In this
state the thread is not seeking the attention of the CPU.

// certain Thread methods put threads into wait( ) states


Wait State Methods

Certain of Thread class methods put a thread into this state
and include wait( ), sleep( ) and yield( ). (The suspend( )
method has been deprecated so we don't count it. )  Notice
wait( ) is not a method defined in the Thread class and
instead is one of the core methods that all classes inherit
from Object.

// wait states ---> ready state ---> running ---> dead


The Blocked Condition

The 'blocked' condition is not caused by a method call.
Instead, it is a behavior that saves on CPU cycles. As an
example, the read( ) methods of the IO classes go into a
blocked state if there is nothing available to read. 


Thread States

 

 Running

 the thread has control of the CPU

 Wait
 States

 caused by wait( ), sleep( ), yield( ) or
 blocked behavior

 Ready

 not waiting for anything except the CPU

 Dead 

 the run( ) method has returned


The Dead State

The final state is the 'dead' state. When run( ) returns
the thread is said to be 'dead'. Dead  threads are unusual
conceptually. Though
they are no longer eligible to run
again, their methods can still be called.

The dead state implies the object is no longer involved in
scheduling behavior however is still resident
in memory
as a callable object. In a sense, a thread in a dead state,
becomes or should we say remains, a regular Java object.


A Baseball Analogy


(If you don't mind a baseball analogy, running is like
being 'up to bat', ready is 'on deck'
and wait states are
like being on the bench. In the preemptive model, the
coach frequently uses pinch hitters putting them ahead
of other players. High priority players get to bat regardless
of how long others have waited.

Round-robin scheduling is like the coach that is fair,
(perhaps to a fault) . Every player goes in turn regardless
if
it will result in the loss of the game.

A dead thread is like a player that finishes his turn at bat
for the last time in the game though he remains in the dug-
out, still technically an active player in the game until the
game is finished.


The Deprecated stop( ) Method

It use to be that to kill a thread the stop( ) method was
called. A lot of early
texts showed many examples of
the stop( ) method being called on a thread. Unfortunately
there
are serious problems with the stop( ) method and
a few of it's associates so they are now
deprecated.

The Java documentation describes emphatically what
deprecations have occurred.
The following table excepts
from an early API the explanation why stop( ), and the
suspend and resume( ) methods were deprecated.

 

  Major Thread Method Deprecations
// excerpted from JDK API documentation


 void stop( ) -deprecated  - inherently unsafe. Stopping a thread
 with Thread.stop causes it to unlock all of the monitors that it has
 locked (as a natural consequence of the unchecked ThreadDeath
 exception propagating up the stack). If any of the objects previously
 protected by these monitors were in an inconsistent state, the

 damaged objects become visible to other threads, potentially
 resulting in arbitrary behavior.

 Many uses of stop should be replaced by code that simply modifies

 some variable to indicate that the target thread should stop running. 
 The target thread should check this variable regularly, and return
 from its run method in an orderly fashion if the variable indicates
 that it is to stop running. If the target thread waits for long periods
 (on a condition variable, for example), the interrupt method should
 be used to interrupt the wait. 

 void suspend( )  -deprecated. as it is inherently deadlock-prone.
 If the target thread holds a lock on the monitor protecting a critical
 system resource when it is suspended, no thread can access this
 resource until the target thread is resumed. If the thread that would
 resume the target thread attempts to lock this monitor prior to calling
 resume, deadlock results. Such deadlocks typically manifest
 themselves as "frozen" processes.

 resume( ) -deprecated. -exists solely for use with suspend( ),
 which has been deprecated as it is prone to deadlock.


 See 'Why are Thread.stop, Thread.suspend  and  Thread.
  resume Deprecated?.',  -@ Sun 


A common recommendation to decommission a thread
is to first call
interrupt( ) on it  then set it's reference to null.

Example    

some_thread.interrupt( );
some_thread = null;

This approach alone doesn't work that well, as the
thread will resume it's activity if not put completely out
of commission somehow.


Alternatives To the stop( ) Method

The recommended interrupt( ) and null combo can be
'ignored' by a stubborn thread and will often need some
help from a control statement.

A way to enforce the interrupt is to use a System.exit( )
in the catch clause. If you don't want to leave the program
but just a loop, a 'break' to a label can be used. These
various techniques are commented out in the following
example. Comment them in one at a time to see them
work.

First there is the deprecated stop( ) method. In the catch
clause there is a System.exit( ), a 'break' statement  and
a 'return' statement that all do the job without the danger
of a 'deadlock' that may occur using the stop( ) method.

Stopping A Thread Sample Code

class _7Up{
public static void main(String args[]){
  Up up = new Up();
  up.start();
  try{
     Thread.sleep(5000);
     }
  catch(InterruptedException ie)
     {
     System.out.println("Outer IOException");
     }  
  up.interrupt();
  up = null;
  
// up.stop( );
// works well but is now 'taboo''      ..........................   1.

  }
}

class Up extends Thread{
 int i;
public void run( ){
  while(true){
      System.out.println(i);
  i++;
  try{ Thread.sleep(1000);}
  catch(InterruptedException ie)
     {
     System.out.println("Time's up for Up");

// System.exit(0); // one way out!  ................................. 2.
// break ; // another way out,(could be used with a label)  3.
//  return;  // return also works to end run  ..................... 4.
   }
  }
 }
}

Using a Variable Flag to End a Loop & Stop a Thread

It is not the best programming practice to use error controls
to control program flow, though this design is used in many
real-time applications. We might consider the above code
an example of the how to use the interrupt( ) method.

A better design is to let Thread's run( ) methods complete
and exit naturally. If a thread has a loop that needs to be
terminated
a boolean  variable can act as a flag to signal
the thread to terminate.

This represents a 'natural death' as the thread is
terminated by the return of the run( ) method.

This approach is shown in the following example.


Flagging a Loop Variable in a String

class Summer implements Runnable
     {
      boolean flag=true;
      public void run( )
         {
          while(flag==true)
        {
             System.out.println("Rain");
             try{Thread.sleep(1000);}
             catch(InterruptedException ie){}
            }
          }
      }
     
      class Winter implements Runnable
     {
      boolean flag=true;
      public void run()
         {
          while(flag==true)
        {
             System.out.println("Snow");
             try{Thread.sleep(1000);}
             catch(InterruptedException ie){}
            }
          }
      }
     
     
class Seasons{
public static void main(String[]args){
      Summer summer = new Summer();
      Winter winter = new Winter();
      Thread thummer = new Thread(summer);
      Thread thinter = new Thread(winter);
      thummer.start();
      thinter.start();
      // lets it rain and snow for 10 seconds
      try{
      Thread.sleep(5000);
      }
      catch(InterruptedException ie){}
      summer.flag=false;
      winter.flag=false;
      System.out.println("A nice exit!");

      }
      }      




Thread Mechanics



Java's Design Was Based on a Thread Model

Java was designed on a foundation that provides support
for threads. In fact, Java runs in a threaded environment.
For instance, Java depends
on a background thread called
the 'gc' thread or 'garbage collector' to automatically free
or 'deallocate' memory that is no longer being used. Java
also assigns the management of painting graphical
components and handling
the events they generate to a
separate thread called the 'Event thread' (aka the AWT
thread ).

The Thread Class

Java supplies these lightweight processes called 'threads'
via instances of the Thread class.
The Thread class
supplies a set of methods to manage the life cycle of
any threads the
developer creates. In Java a thread is
an instance of the Thread class. Thread is one of the
fundamental language classes in the
java.lang package
and does not require any explicit package imports.

// Java threads are instances of the java.lang.Thread class

A Java Thread object can be thought of as a Virtual Central
Processing unit or Virtual CPU. In this
analogy the thread's
start( ) method serves to turn the CPU on. The run( ) method
is supplies to the
thread process what main does for a stand-
alone Java program.
The run( ) method supplies the point of
entry for the activities that will be executed by
the thread.
Any number of such threads of activity can be created within
the practical
limits of the system's memory and performance
characteristics.

Comparing a Thread to a Java Virtual Machine running a main( ) Application
 

 Virtual Machine

 Thread 

 central processing unit

 Thread object   // dynamic part

 power on  // call 'java' on program

 start( ) method

 main(  ) method 

 run( ) method



Details of Thread Activity in the Java Virtual Machine

Each Java application runs in a single instance of the
Runtime class. Runtime
defines methods like exec( )
and exit( ). The exit( ) method initiates a shutdown

sequence for the current runtime object. Typically, the
exit( ) method is called from the System class, as in
the following.


Example

System.exit(0);

// zero indicates a normal exit

The 0 int value is a status code are used to indicate a
normal exit. Non-zero status codes indicate
abnormal
halts.

For interests sake, the following Runtime class demo
shows the getRuntime( ) method invoked, exec( ) used
to start an copy of notepad and a call on freeMemory( )
to check memory.  Other exec( ) methods allow fancier
command executions.


Runtime Class Demo

import java.io.*;

class RuntimeInfo{
public static void main(String[] args){
  try
  {
  Runtime rt= Runtime.getRuntime();
  rt.exec("notepad");
  System.out.println("You should see notepad running if on Windows");
  System.out.println("Free Memory: " + rt.freeMemory());
  }
  catch(IOException io)
  {
   System.out.println(io );
  }
  }
}


 A Single Non-daemon Thread Calls main( )

Aside from the background threads such as the Garbage
Collector and the Event
thread the Java Virtual Machine
starts a single, non-daemon thread that calls
the main( )
method of the class that has been supplied as a parameter
to the 'java
' runtime command.

// daemon threads are background threads

This thread and any others that are started will run until
one of
two conditions occur. Either the exit( ) method is
called in the runtime environment,
(and the security manager
has permitted the exit to happen), or all the non-daemon

threads have died. The non-daemon threads will have
died either by having their
run( ) methods return or by
throwing an exception that propagates beyond the name

scope of the run( ) method.

 
Conditions that Stop the Runtime Thread


Thread Support

Most thread support resides in class Thread. There is a
special kind of support
that allows thread activity to be
coordinated and communicating that resides in
the Object
class. There is also some additional help supplied by the
Runtime
Environment.

Thread Exception Progogation

Exception propagation in a thread instance is limited to
the thread
so a problem in one thread will not to interfere
with the activities of other
processes. Thread class has
the following declaration.

Thread Class Signature

public class Thread extends Object implements Runnable 

// Thread implements Runnable

 

The Runnable Interface

The Runnable interface defines the single method run( )
as shown in the interface
declaration below. When run( )
is overridden, it must be declared public, returning void
and taking no
arguments. It is inside the run( ) method
that the work that is being given to the
thread is contained.


The Runnable Interface

public interface Runnable {
       public void run( );
      }


Two Approaches To Creating Threads



There are two basic approaches to creating threads.
You
can either extend Thread
class and thereby inherit
the Runnable behavior or you can implement
Runnable
in a class that becomes a target for a Thread constructor.

These two variations can be summarized as follows.

Two Basic Approaches to Creating Threads

1) Subclass Thread and override run( )
2) Target an object that implements Runnable


Subclass Thread 
// an advantage and a work-around

Extending Thread has the advantage of making it's
methods readily available for
use in the subclass. This
isn't so when implementing Runnable. There is though
a work-around. A reference to the currently executing
thread can be obtained via the
static call on the method
currentThread( ) from inside run( ). Then Thread class

methods can be called using this reference.


Example
 

Thread current = Thread.currentThread( )

Extending Thread is not always possible because of
Java's single inheritance model.
For instance, applets
extend Applet class therefore cannot also extend Thread.
An
applet's only choice is to implement Runnable.

First we consider the technique where Thread is subclassed.  

A summary of the steps involved are as follows:

Subclassing Thread Approach

1) extend Thread
2) override run( ) in the subclass
3) create an instance of the subclass and call start( ) on it.      

// start calls run( )

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( );
        }

     }
 

Target a Runnable Object

The second approach involves creating a class that
implements the Runnable interface. This class is
instantiated and supplied as an argument to a Thread
class constructor. This is summarized in the following
steps.

Summary of Approach Targeting a Runnable Object

1) Create a class which implements Runnable
2) Provide an instance of Runnable to a Thread constructor
3) Instantiate and call start( ) on the instance

For this approach, the thread constructor with the following
form is used.
The Runnable target instance provides the
implementation of the method.

Example  

public Thread(Runnable target)


Code where a Runnable Object is Targeted by a Thread Constructor

 class TargetClass implements Runnable{
     public void run( ){
         System.out.println
         ("Thread takes target and starts it's run");
         }
    }

 class TargetRun{
    public static void main(String[]args){
        TargetClass  target = new TargetClass( );
        Thread arrow = new Thread(target);
        arrow.start( );
        }
    }

In both cases the run( ) method is overridden and
the start( ) method is called on the Thread object.


Key Thread Class Methods



The sleep( ) Method 

We used the sleep( ) method above. The sleep( ) method
is a static method, which causes the currently executing
string to
'time-out' for a time specified in milliseconds, or
milliseconds and
nanoseconds Time is accurate only in
the respect that the thread won't re-enter until that time
elapses. It goes into the ready state in which condition
there
is no guarantee when it will run again.

// guarantees to sleep( ) the given time, not when it runs

The sleep( ) method throws InterruptedException.  As long
as the exception is not thrown the method guarantees a
minimum amount of
sleep time. The sleep( ) method is
very useful in a number of applications, for instance to
introduce periodicity into
visual animations.

Sample Code showing sleep( ) being used

class Counter extends Thread{
// Press Control-C to end
public void run(){
   int count=0;
 while(true){
     count=count+1;
     System.out.println(count);
   try{
   Thread.sleep(1000);
   }catch(InterruptedException ie){ }
   }
  }
 }

class Count{
public static void main(String[] args){

  Counter count=new Counter();
  count.start();

  }
 }


The yield( ) Method

yield( ) is a static method which moves the executing
thread to ready state where
it waits or re-executes.
Calling yield( ) at regular intervals ensures a single
process
doesn't monopolize the CPU, permitting other
threads to execute. To ensure the
thread is checked
occasionally, the time-consuming thread is set to a
priority that is lower than the thread that needs to be
checked occasionally and yield( ) is called
periodically
to let the occasional thread to run.

// set time consuming thread to lower priority than thread
// that takes little time

The following code ( in green )shows yield( ) being used.
Each class that runs in it's own thread shows a different
character pattern on screen. 

On Linux, when both threads yield( ) within their loops they
share the CPU evenly. Without yields the output is a bit of
a 'free-for-all' where there is erratic sharing.

Using sleep( ) with the sleep times of each thread using
different ratios seems to allow reasonably predictable
control over how much time each thread would have at the
CPU.

Try the following on Windows and compare the behaviour
to that of Linux.


yield( ) Code Example

// use Ctrl_C to stop process

class Lots extends Thread{
public void run(){
 while(true){
   System.out.print("|||||");
   

//  Using sleeps with different ratios  of sleep times
//  seems like a better way to get proportional runtime
// behavior
 
 // try{Thread.sleep(300);}catch(InterruptedException ie){ }
 
 // commenting in yields in one thread or the other
 // causes one thread to predominate but still allowing
 // the other to run
 
 // when both threads yield there is shared behavior
 
 
// Thread.yield( );

   }
  }
 }


class Little extends Thread{
public void run(){
  while(true){
   System.out.print("-----");


//      try{Thread.sleep(100);}catch(InterruptedException ie){ }

//   Thread.yield( );
  
}
  }
 }

class LotsLittle{
public static void main(String[] args){

  Lots lots=new Lots();
  Little little=new Little();

//  lots.setPriority(5);
//  little.setPriority(5);

// setting priorities did not have a discernible
// effect on Linux on 8086 architecture

 
  lots.start( );
   little.start( );
   }
 }

OUTPUTS  // Linux on 8086

a ) Code as is, an erratic mix of all one character or the other

---------------------------------------------------------
---------------------------------------------------------
---------------------------------------------------------
---------------------------------------------------------
---------------------------------------------------------
|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||



b) Uncommenting yield( ) methods yields nice shared
 behavior, at least on Linux on 8086.

-----|||||-----|||||-----|||||-----|||||-----|||||-----|||||-----|||||
|||||-----|||||-----|||||-----|||||-----|||||-----|||||-----|||||-----
-----|||||-----|||||-----|||||-----|||||-----|||||-----|||||-----|||||
|||||-----|||||-----|||||-----|||||-----|||||-----|||||-----|||||-----
-----|||||-----|||||-----|||||-----|||||-----|||||-----|||||-----|||||
|||||-----|||||-----|||||-----|||||-----|||||-----|||||-----|||||-----


c ) Using sleep( ) with different ratios of sleep time
was effective in controlling proportionately how long
one thread would run relative to the other.

||||||||||-----||||||||||-----||||||||||-----||||||||||-----||||||||||-----||||||||||
-----||||||||||-----||||||||||-----||||||||||-----||||||||||-----||||||||||-----
||||||||||-----||||||||||-----||||||||||-----||||||||||-----||||||||||-----||||||||||
-----||||||||||-----||||||||||-----||||||||||-----||||||||||-----||||||||||-----
||||||||||-----||||||||||-----||||||||||-----||||||||||-----||||||||||-----||||||||||
-----||||||||||-----||||||||||-----||||||||||-----||||||||||-----||||||||||-----



d ) Setting priorities had little discernible effect on this
    machine.


The interrupt( ) Method

To causes a thread to abandon a process such as an
I/O operation interrupt( ) can
be called. Calling interrupt( )
causes an InterruptedException to be thrown. You can

catch this exception to implement a 'time-out' in a
process. For example,


Example

catch(InterruptedException ie) {
        break;
        }

The interrupt(  ) method was demonstrated in the code
sample shown earlier called _7UP.
 

The join( ) Method

The join( ) method provides a way to allow one thread
to stop what it is doing
until another thread is completely
finished it's activity. This method provides a
rudimentary
form of communication between threads as one thread
is allowed
to complete before the next thread is started.

In the following example, two threads are created that
both more or less take turns accessing the CPU. By
uncommenting
the join( ) method, one of the threads
'politely' waits until it's associate thread
has completely
finished.


Code demonstrating the use of join( )

class Blue extends Thread
 {
 Blue(String s)
  {
  super(s);
  }
 public void run()
  {
    int count=0;
  for(int i=0;i<10;i++)
    {
     count=count+1;
     System.out.println(getName() + "  " + count);
    try
     {
     Thread.sleep(300);
     }
     catch(InterruptedException ie)
     {
     }
    }  // for
  }  // run
 }  // class

class Red extends Thread
 {
 Red(String s)
  {
  super(s);
  }
public void run( )
  {
   int count=0;
  for(int i=0;i<10;i++)
   {
     count=count+1;
     System.out.println(getName() + "  " + count);
   try
   {
   Thread.sleep(300);
   }
   catch(InterruptedException ie)
   {
   }   
  }  // for
 }  // run
// class
 
// try different combinations of join

class RedBlue
 {
  public static void main(String[] args)
  {
  Red red=new Red("Red  Thread");
  Blue blue=new Blue("Blue Thread");

// start with try catch block and join commented out
// try{   
  red.start( );
 //   red.join( );  
  blue.start( );
//  don't need to join( ) blue as red is not re-contending
//  }                  
 //  catch(InterruptedException ie){/*report*/}

 } // main
} // class

Blocking

Blocking is not a method, but a behavior. when forced
to wait on some external
factor, the thread steps out of
the running state and is said to be blocked. For instance,

when a method has to wait to read from a socket, the
method  will 'try' to read a byte
immediately. If none is
available, rather than tying up the running state, the method

'steps out' of the way and is said to be blocked (All Java
IO methods are designed
to behave this way).
 

The setDaemon( ) Method

The setDaemon( ) method makes a thread a 'daemon'
versus a 'user' thread. In Java
a daemon thread is a
service provider whose value is predicated on a user
thread being present. The JVM can only exit if zero
user threads are running.

If you want a thread to run but not prevent a user from
exiting the JVM, making the thread a
daemon thread
will accomplish this. Making a service a daemon thread
takes care
of freeing the resources associated with the
thread should the main server terminate.

Example       

thisService.setDaemon(true);


daemon // around Kitchener-Waterloo often pronounced day-mon

Pronounced "demon." A UNIX program that executes in the
 background ready to perform an operation when required.
 Functioning like an extension to the operating system, a
 daemon is usually an unattended process that is initiated
 at startup. Typical daemons are print spoolers and e-mail
 handlers or  a scheduler that starts up another process at
 a designated time.
 The term comes from Greek mythology meaning "guardian
 spirit."

                                                   - the TechEncylopodia

  // also pronounced like 'diamond' as in Raphael


Deprecated methods suspend( ), resume( ) & stop( )

Just for completeness we re-confirm the deprecation of
the suspend( ), resume(  )
and stop( ).  In the case of the
suspend( ) method a thread receiving a suspend call
stays
suspended until it receives a resume( ) call. A thread can
be suspended by
itself or another thread but only resumed
by another thread. A suspended thread
can easily become
permanently suspended as it cannot reactivate itself. A
resume( )
call on a thread that is not suspended is simply
ignored. The deprecation of the stop( )
method makes the
interrupt( ) method more important then before.

 

The Thread class has many interesting constructors and
methods. It is worth taking
a few minutes to visit the class
in the JDK documentation.

 


Self Test  Multithreading Basics            Self Test With Answers


1) Which of the following terms is used almost exclusively to describe
     processes with processes?

a) multiprogramming
b) time sharing
c) multitasking
d) multithreading

2)  Regarding preemptive multithreading which of the following statements is least
correct?
a) threads with higher priority preempt threads with lower priority
b) the preemptive model affords some predictability with respect to which
    processes will be run
c) Java's preemptive model is unaffected by the underlying system's thread model.
d) If all threads are given equal priority values they will behave more or less like
    a time-sliced system.
 

3) Which of the following is least correct in describe the different states threads
can assume?
a) Running
b) Blocked
c) Ready
d) Dead

4) Which of the following variations that result in the creation of wait states is a
method but is not defined in the Thread class.
a) yield( )
b) wait( )
c) block
d) sleep( )

5) In comparing an thread instance of a Java multithreaded environment to a virtual
computer system, calling the start( ) method can be thought of as corresponding to
which of the following?

a) a Virtual Machine
b) main( ) method
c) Power On
d)  a CPU

6) Consider the two approaches to obtaining Thread behavior. When the
Runnable interface is implemented which of the following is not correct?

a) The Thread class constructor targets the Runnable object.
b) Both the Thread object and Runnable object are instantiated.
c) The Runnable object will supply a definition for the run( ) method.
d) The start( ) method is called on the Runnable object.


Exercise



Please be careful to note and answer all the questions!

1) Create seven Thread classes each a Thread extension
named after each day of the week. Have each print to screen
what day they are from inside Runnable's run( ) method.
Instantiate each in another class that has a main( ) method.
Call on a reference for each the start( ) method. Run the main
class and briefly describe what you observe with respect to
order.

2) Because each class will execute so quickly their order
will dictate largely when they will execute. Add the following
lines to the run( ) method ahead of the System.out.println( )
statement so they have an more even chance in the 'race'.

public void run( ){
try{Thread.sleep((int)(Math.random()*50+1));}
catch(InterruptedException ie){ie.toString();}
// etc

2) Apply thread priorities to attempt to attempt to have the days
print in the correct order. Run the prioritized threads several
times. In Linux the method had little or no effect. What do
you observe on Windows XP?

Example 

lots.setPriority(5);


3) Comment out the priority setting methods. In the main
method( ), immediately following each thread's start( ) call,
call the join( ) method on the thread's reference.

Example  

monday.start( ) ;
monday.join( );

What effect did the join method have on the output?


4) Create Runnable interfaces for the 4 seasons where
each Runnable will print to screen the name of the season
associated with the object.

Use the second technique discussed for creating thread
objects where the Runnable object is supplied to a Thread
constructor to create 4 threads representing the seasons
that print the Season names to screen.

4) Modify the constructor used to include names. Use the
getName() method to output these names to screen.