Understanding Threads


A thread is a single sequential flow of control within a program. It is born, it runs, and then it dies. A thread has its own execution stack and program counter. In fact, the CPU runs one thread at a time. Chip manufacturers have gotten clever by packing memory around the CPU so that several threads have a place to wait in memory, but the CPU runs only one thread at a time. The CPU has some smarts about prioritizing threads. The specifics of how thread priorities affect scheduling are platform dependent. The Java specification just states that threads must have priorities, but it does not dictate what the scheduler should do about priorities. In a non-preemptive model, the scheduler gives higher priority threads more of a chance to run, but not necessarily get CPU time immediately. The CPU processes threads in pieces, not the entire thread at once. This piecemeal approach allows the CPU to switch between threads governed by the scheduler. That way, multithreading can occur.

Java has strong multithreading capabilities. Multithreading was an early consideration when the designers at Sun started work on Java. Many languages also have this capability, but Java's application programming interface (API) for threads is simple to use and works as advertised.

graphics/tip_icon.gif

How should you add multithreading? Design a block of code so that it works. After you are sure it's bug free, add multithreading. Don't add multithreading upfront because it complicates the design needlessly.


Take a look at a code sample of an application that isn't thread safe, but should be. Listing 10.1 is an application that illustrates a simple problem: one part of the program being accessed simultaneously by too many other parts .

Listing 10.1 An Application Using Multithreading
 public class MultiThread1 {     public static void main( String [] args )     {         System.out.println( "Main Start" );         //determine number of new threads         int numberOfThreads = 10;         for(int i = 0; i < numberOfThreads; i++)         {             // create a new thread             new NewThread( "Thread number " + i ).start();         }         System.out.println( "Main Done" );     } } // a new thread class class NewThread extends Thread {    // give thread a name    public NewThread( String threadName )    {       super( threadName );       System.out.println( "created " + threadName );    }    // override the run method in Thread    public void run()    {       // try to make thread sleep       try       {           // create sleep duration in milliseconds = 0-10 seconds           int milliseconds = ( int ) ( Math.random() * (10000 + 1));           int seconds = ( int ) milliseconds / 1000;           String status = "NewThread name = " + getName()                     + "; napping for "                     + seconds                     + " seconds.";           System.out.println( status );           Thread.sleep( milliseconds );           // tell system thread is awake           status = getName() + " is getting up from napping.";           System.out.println( status );       // Oops, interrupted       } catch ( InterruptedException ex )       {          ex.printStackTrace();       }    } } /* results vary between runs: Main Start created Thread number 0 created Thread number 1 created Thread number 2 NewThread name = Thread number 0; napping for 3 seconds. NewThread name = Thread number 1; napping for 5 seconds. created Thread number 3 created Thread number 4 created Thread number 5 created Thread number 6 created Thread number 7 created Thread number 8 NewThread name = Thread number 2; napping for 8 seconds. NewThread name = Thread number 3; napping for 4 seconds. NewThread name = Thread number 4; napping for 3 seconds. NewThread name = Thread number 5; napping for 8 seconds. NewThread name = Thread number 6; napping for 5 seconds. NewThread name = Thread number 7; napping for 1 seconds. created Thread number 9 Main Done NewThread name = Thread number 8; napping for 0 seconds. NewThread name = Thread number 9; napping for 1 seconds. Thread number 8 is getting up from napping. Thread number 7 is getting up from napping. Thread number 9 is getting up from napping. Thread number 4 is getting up from napping. Thread number 0 is getting up from napping. Thread number 3 is getting up from napping. Thread number 1 is getting up from napping. Thread number 6 is getting up from napping. Thread number 5 is getting up from napping. Thread number 2 is getting up from napping. */ 

There are two classes in the program shown in Listing 10.1. NewThread is a simple class that represents a single thread. It puts itself to sleep for a random amount of time and then wakes again. The MultiThread1 class plays the master role, spawning several instances of the NewThread object. As you can see from the printout commented at the end of the listing, the threads do indeed start and stop out of order because of their different sleep lengths. Theoretically, MultiThread1 could spawn several different instances of NewThread so that 10 of the threads are alive simultaneously. That would mean 10 threads are active at the same time. With Java, you can handle this multithreaded situation easily.

Perhaps the program could be adjusted somewhat so that MultiThread has more control over the NewThread instances. Listing 10.2 is a better example of one object having more control over the threads it spawns.

Listing 10.2 One Object Spawning Sleeping Threads
 public class MultiThread2 {     public static void main( String [] args )     {         //determine number of new threads         int numberOfThreads = 10;         if (args.length == 1)         {             numberOfThreads = Integer.parseInt(args[0]);         }         System.out.println( "Main Start" );         for(int i = 0; i < numberOfThreads; i++)         {             // create sleep duration in milliseconds = 0-10 seconds             int milliseconds = ( int ) ( Math.random() * (10000 + 1));             // create a new thread             new NewThread( "Thread number " + i, milliseconds ).start();         }         System.out.println( "Main Done" );     } } // a new thread class class NewThread extends Thread {     int milliseconds = 10000;    // give thread a name    public NewThread( String threadName, int milliseconds )    {       super( threadName );       this.milliseconds = milliseconds;       System.out.println( "created " + threadName );    }    // override the run method in Thread    public void run()    {       // try to make thread take a nap       try       {           int napLength = ( int ) milliseconds / 1000;           String status = "NewThread name = " + getName()                     + "; napping for "                     + napLength                     + " seconds.";           System.out.println( status );           Thread.sleep( milliseconds );           // tell system thread is awake           status = getName() + " is getting up from napping.";           System.out.println( status );       // Oops, interrupted       } catch ( InterruptedException ex )       {          ex.printStackTrace();       }    } } //results look like that of Listing 10.1 

Listing 10.2 demonstrates how easy it is to control a thread from another object. In fact, in this code 11 threads were running. There is a thread for the MultiThread object and one thread for each NewThread object. In the following section, you see another way to control a thread.



JavaT 2 Developer Exam CramT 2 (Exam CX-310-252A and CX-310-027)
JavaT 2 Developer Exam CramT 2 (Exam CX-310-252A and CX-310-027)
ISBN: N/A
EAN: N/A
Year: 2003
Pages: 187

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net