CS 596 Java Programming Fall Semester, 1998 Threads, part 1 |
||
---|---|---|
© 1998, All Rights Reserved, SDSU & Roger Whitney San Diego State University -- This page last updated 13-Nov-98 |
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
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()
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() |
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
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
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
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() ); } } }
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 TestThreadOutput- 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
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 classNameIt 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.
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 Processor | On Multiple Processor Rohan |
0 From: Thread-5 | End |
1 From: Thread-5 | 0 From: Thread-3 |
2 From: Thread-5 | 1 From: Thread-3 |
3 From: Thread-5 | 2 From: Thread-3 |
4 From: Thread-5 | 0 From: Thread-2 |
0 From: Thread-4 | 3 From: Thread-3 |
1 From: Thread-4 | 1 From: Thread-2 |
2 From: Thread-4 | 2 From: Thread-2 |
3 From: Thread-4 | 4 From: Thread-3 |
4 From: Thread-4 | 3 From: Thread-2 |
End | 4 From: Thread-2 |
Thread Scheduling Single Processor -Time-slicing or not time-sliced
Time-slicing
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
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"
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 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 ByeCopyright © 1998 SDSU & Roger Whitney, 5500 Campanile Drive, San Diego, CA 92182-7700 USA.
All rights reserved.
visitors since 28-Oct-98