SDSU CS 596 Java Programming
Fall Semester, 1998
Threads, part 1
To Lecture Notes Index
© 1998, All Rights Reserved, SDSU & Roger Whitney
San Diego State University -- This page last updated 13-Nov-98

Contents of Doc 18, Threads, part 1


References


The Java Programming Language, 2 nd Ed. Arnold & Gosling, Addison-Wesley, 1998

Java 1.2b4 on-line documentation

Listen Here!S-nov2 10mins Doc 18, Threads, part 1 Slide # 2

Concurrent Programming


The ability to perform concurrent programming is part of the Java programming language. That is different parts of the same program can be executing at the same time, or behave if they are executing at the same time. Java uses threads to achieve concurrency. Writing concurrent programs presents a number of issues that do not occur in writing sequential code.

Safety
Two different threads could write to the same memory location at the same time, leaving the memory location in an improper state.

Liveness
Threads can become deadlocked, each thread waiting forever for the other to perform a task. Threads can become livelocked, waiting forever to get their turn to execute.

Nondeterminism
Thread activities can become intertwined. Different executions of a program with the same input can produce different results. This can make program hard to debug.

Communication
Different threads in the same program execute autonomously from each other. Communication between threads is an issue.


Listen Here!S-nov2 1min Doc 18, Threads, part 1 Slide # 3

Threads


A thread is an active entity that shares the same name space as the program that created the thread. This means that two threads in a program can access the same data.


Difference from fork()

fork()
Child process gets a copy of parents variables
Relatively expensive to start
Don't have to worry about concurrent access to variables

thread
Child process shares parents variables
Relatively cheap to start
Concurrent access to variables is an issue



Thread Class Methods

activeCount()interrupt() setDaemon(boolean)
checkAccess()interrupted() setName(String)
countStackFrames()isAlive() setPriority(int)
currentThread()isDaemon() sleep(long)
destroy()isInterrupted() sleep(long, int)
dumpStack()join() start()
enumerate(Thread[])join(long) stop()
getName()join(long, int) stop(Throwable)
getPriority()resume() suspend()
getThreadGroup()run() toString()
yeild()


Listen Here!S-nov2 7mins, Q-nov5 10mins Doc 18, Threads, part 1 Slide # 4

Creating Threads


There are two different methods for creating a thread: extending the Thread class or implementing the Runnable interface. The first method is shown on this slide, the second on the next slide.

In the Thread subclass, implement the run() method. The signature of run() must be as it is in this example. run() is the entry point or starting point (or main) of your thread. To start a thread, create an object from your Thread class. Send the "start()" method to the thread object. This will create the new thread, start it as an active entity in your program, and call the run() method in the thread object. Do not call the run() method directly. Calling the run() directly executes the method in the normal sequential manner.

class  SimpleThread  extends Thread {
   public void run() {
      for  ( int  count = 0;  count < 4; count++)
         System.out.println( "Message " + count +
                          " From: Mom" );
   }
}
class  TestingSimpleThread {
   public static void main( String[]  args ) {
      SimpleThread  parallel  = new SimpleThread();
      System.out.println( "Create the thread");
      parallel.start();
      System.out.println( "Started the thread" );
      System.out.println( "End" );
   }
}
Output
Create the thread
Started the thread
End
Message 0 From:  Mom
Message 1 From:  Mom
Message 2 From:  Mom
Message 3 From:  Mom

Listen Here!S-nov2 3mins, Q-nov5 2mins Doc 18, Threads, part 1 Slide # 5
Second Method for Creating a Thread

First, have your class implement the Runnable interface, which has one method, run(). This run() plays the same role as the run() in the Thread subclass in the first method. Second, create an instance of the Thread class, passing an instance of your class to the constructor. Finally, send the thread object the start() method.

class  SecondMethod  implements  Runnable {
   public  void  run() {
      for  ( int  count = 0;  count < 4; count++)
         System.out.println( "Message " + count +  " From: Dad");
   }
}
class  TestThread {
   public static void main( String[]  args ) {
      SecondMethod  notAThread  = new SecondMethod();
      Thread  parallel  =  new Thread( notAThread );
      System.out.println( "Create the thread");
      parallel.start();
      System.out.println( "Started the thread" );
      System.out.println( "End" );
   }
}
Output
Create the thread
Started the thread
End
Message 0 From: Dad
Message 1 From: Dad
Message 2 From: Dad
Message 3 From: Dad

Listen Here!S-nov2 1min Doc 18, Threads, part 1 Slide # 6
Giving a Thread a Name
We can give each thread a string id, which can be useful.

class  SecondMethod  implements  Runnable {
   public  void  run() {
      for  ( int  count = 0;  count < 2; count++)
         System.out.println( "Message " + count +  " From: " + 
                        Thread.currentThread().getName() );
   }
}
class  TestThread {
   public static void main( String[]  args ) {
      Thread  a  =  new Thread(new SecondMethod(), "Mom" );
      Thread  b  =  new Thread(new SecondMethod(), "Dad" );
      System.out.println( "Create the thread");
      a.start();
      b.start();
      System.out.println( "End" );
   }
}
Output
Create the thread
End
Message 0 From: Mom
Message 1 From: Mom
Message 0 From: Dad
Message 1 From: Dad

Listen Here!S-nov2 55secs, Q-nov5 1min Doc 18, Threads, part 1 Slide # 7
SimpleThread for Use in Future Examples

This class will be used in future examples.

public class  SimpleThread  extends Thread
   {
   private  int  maxCount =  32;
   public  SimpleThread(  String  name )
      {
      super( name );
      }
   public  SimpleThread(  String  name, int repetitions )
      {
      super( name );
      maxCount  =  repetitions;
      }
   public  SimpleThread(  int repetitions )
      {
      maxCount  =  repetitions;
      }
   public  void run()
      {
      for  ( int  count = 0;  count < maxCount; count++)
         {
         System.out.println( count + " From: " + getName() );
         }
      }
   }

Listen Here!S-nov2 5mins, Q-nov5 4mins Doc 18, Threads, part 1 Slide # 8
Show Some Parallelism
In this example we show some actual parallelism. Note that the output from the different threads is mixed.

class  TestThread
   {
   public static void main( String[]  args )
      {
      SimpleThread  first      = new SimpleThread( 5 );
      SimpleThread  second  = new SimpleThread( 5 );
      first.start();
      second.start();
      System.out.println( "End" );
      }
   }
Command Line to Execute the Program

java -native TestThread
Output- On Rohan Using Native Threads
End
0 From: Thread-0
1 From: Thread-0
2 From: Thread-0
0 From: Thread-1
1 From: Thread-1
2 From: Thread-1
3 From: Thread-0
3 From: Thread-1
4 From: Thread-0
4 From: Thread-1

Doc 18, Threads, part 1 Slide # 9

Solaris, Green & Native Threads


In the beginning, Java on Solaris machines used Green threads (Green being the name of the originator, note the actual color of the software). A Java program using Green threads runs in one Solaris thread. This means the program runs on one processor. Starting with Solaris 2.6 (or Solaris 2.5 with proper patches) and JDK 1.1, Java supports the use of native Solaris threads. On multiprocessor machines like Rohan, native Solaris threads are scheduled on different processors. Thus, a Java program using native threads can use multiple processors on Rohan.

The default is JDK 1.1 is to use green-threads, except for a special (and rather buggy) release of JDK 1.1.3. To use native threads with JDK 1.1 or JDK 1.2b4 on a Solaris machine use the flag -native:

java -native className
It is easy (if you have the proper authority) to change the default to native threads. Given that Java has problem with native threads on Solaris 2.5 and earlier, it is not clear if the default on JDK 1.2 will be Green or native Solaris threads.


Listen Here!S-nov2 7mins, Q-nov5 1min Doc 18, Threads, part 1 Slide # 10

Thread Scheduling

Preemptive

Priorities

Each Java thread has a priority. The values of a thread priority are integer values ranging from java.lang.Thread.MIN_PRIORITY and java.lang.Thread.MAX_PRIORITY. That is currently from 1 to 10. When code running in some thread creates a new Thread object, the new thread has its priority initially set equal to the priority of the creating thread. A thread is always run before other threads with lower priorities. A program starts execution in a thread of Thread.NORM_PRIORITY (that is 5). The following example shows how to set the priority of a thread and some interesting output.


class  TestThread
   {
   public static void main( String[]  args )
      {
      SimpleThread  first      = new SimpleThread( 5 );
      SimpleThread  second  = new SimpleThread( 5 );
      second.setPriority( 8 );
      first.start();
      second.start();
      System.out.println( "End" );
      }
   }
Output
On Single ProcessorOn Multiple Processor Rohan
0 From: Thread-5End
1 From: Thread-50 From: Thread-3
2 From: Thread-51 From: Thread-3
3 From: Thread-52 From: Thread-3
4 From: Thread-50 From: Thread-2
0 From: Thread-43 From: Thread-3
1 From: Thread-41 From: Thread-2
2 From: Thread-42 From: Thread-2
3 From: Thread-44 From: Thread-3
4 From: Thread-43 From: Thread-2
End4 From: Thread-2


Listen Here!S-nov2 4mins Doc 18, Threads, part 1 Slide # 11
Thread Scheduling

Single Processor -Time-slicing or not time-sliced


Time-slicing
A thread is run for a short time slice and suspended,
It resumes only when it gets its next "turn"
Threads of the same priority share turns
Java does not specify if the scheduler must use time-slicing, so some implementations, do some do not.

Java running Green threads on Solaris does not time-slice

Non time-sliced threads run until:
They end
They are terminated
They are interrupted
Higher priority threads interrupts lower priority threads
They go to sleep
They block on some call
Reading a socket
Waiting for another thread
They yield


Doc 18, Threads, part 1 Slide # 12
Setting Priorities

Continuously running parts of the program should have lower-priority than rarer events

User input should have very high priority

A thread that continually updates some data is often set to run at MIN_PRIORITY

Listen Here!S-nov2 2mins Doc 18, Threads, part 1 Slide # 13
Testing for Time-slicing & Parallelism

class  InfinityThread  extends Thread
   {
   public  void run()
      {
      while ( true )
         System.out.println(  "From: " + getName() );
      }
   }
class  TestThread
   {
   public static void main( String[]  args )
      {
      InfinityThread  first      = new InfinityThread( );
      InfinityThread  second  = new InfinityThread( );
      first.start();
      second.start();
      }
   }
Output if Time-sliced

A group of "From: Thread-a" will be followed by a group of "From: Thread-b" etc.

Output if not Time-sliced, Single Processor

"From: Thread-a" will repeat "forever"

Multiple Processor
"From: Thread-a" and "From: Thread-b" will intermix "forever"

Listen Here!S-nov2 2mins, Q-nov5 1min Doc 18, Threads, part 1 Slide # 14

Types of Threads: user and daemon


We have seen several examples now of a program that continues to execute after its main has finished. So, when does a Java program end? To answer this question we need to know about the different types of threads. There are two types of threads: user and daemon.

Daemon thread
Daemon threads are expendable. When all user threads are done, the program ends all daemon threads are stopped

User thread

User threads are not expendable. They continue to execute until their run method ends or an exception propagates beyond the run method.

When a thread is created, it is the same type of thread as its creator thread. The type a thread can be changed before its start() method is called, but not after its start() method has been called. See example on next slide. The main of your program is started in a user thread.

The Java Virtual Machine continues to execute the program until either of the following occurs:




Listen Here!S-nov2 3mins, Q-nov5 2mins Doc 18, Threads, part 1 Slide # 15
Daemon example

The thread "shortLived" has the same priority as the thread running main. Hence on a single processor machine, "shortLived" will not start until main ends or main uses up its time-slice. Main is short enough to finish in one time-slice. However, since "shortLived" is a daemon thread, it does not run after all the user threads are done. Hence, "shortLived" never starts and does not print anything.

class DaemonExample
   {
   public  static  void  main( String  args[] )
      {
      InfinityThread  shortLived      = new InfinityThread( );
      shortLived.setDaemon( true );
      shortLived.start();
      System.out.println( "Bye");
      }
   }
class  InfinityThread  extends Thread
   {
   public  void run()
      {
      while (true)
         {
         System.out.println(  "From: " + getName()  );
         System.out.flush();
         }
      }
   }
Output
Bye
Copyright © 1998 SDSU & Roger Whitney, 5500 Campanile Drive, San Diego, CA 92182-7700 USA.
All rights reserved.

visitors since 28-Oct-98