Please support my sponors and make this site possible!!!
Please support our sponsors!

 

Home > Core Java FAQ > Threads FAQ
Threads 
Creating and Controlling (07)   *  Thread Interactions(10)  *  User Threads versus System Threads(04) 
 
Q . What is a thread?

Ans : 

A thread is a sequence of executing instructions that can run independently of other threads yet can directly share data with other threads.

     Threads let you organize your program into logically separate paths of execution. Multiple threads are like independent agents at your disposal. You give each one a list of instructions and then send it off on its way. From the individual thread's perspective, life is simple: it works on its own list of instructions until it either finishes the list or is told to stop. In this respect, a thread resembles a process, or a separately running program.
     Data sharing among threads, however, can make the programmer's life quite complex. All memory for objects (that is, class instances and arrays) is allocated from system-managed memory shared by all Java threads. One thread could change the color of a Button instance, for example, and that change would be immediately visible to any other thread holding a reference to the same Button instance. (Not all data is shared between threads, though—Java threads each have their own execution stack, which keeps local variables and method arguments private to a thread.) Data sharing means that threads can interact with each other in surprising ways, and at the most unexpected times. Like a house of mirrors, unconstrained thread interactions can make objects suddenly appear or disappear, or values mysteriously change. You must work carefully to control how your threads access shared resources, so that each thread can read and write data accurately.
     Despite the dangers, programming with threads typically provides significant advantages, including:

  • reduced difficulty in writing highly interactive, multifaceted programs
  • increased throughput of data
  • improved performance on multiprocessor hardware
     The main power of multithreaded programming lies in letting you tackle different tasks (very nearly) independently, leaving the worries of time sharing among tasks to the operating system or virtual machine. A web browser, for example, can use one thread to format and display the text of a web page as soon as it arrives, while other threads manage the slower downloading of large image or sound files. Without threads, the browser authors would have to pollute their text display code with periodic checks for new image data and with calls into the separate body of code to handle image data. What's more, adding a new operation to be performed while images are downloading would require yet more code intermingling, interruption, and greater potential for confusion and bugs.
     Second, program throughput usually improves in multithreaded programs. Blocking one part of the program, such as the image fetch just mentioned, doesn't prevent other parts from getting their own work done.
     Third, multiprocessor systems are becoming increasingly common and important. A program written with multithreading from the ground up can benefit directly and strongly from running different threads concurrently on different processors.
     Integrated support for threads is a key facet of Java technology. As explained further on in this chapter, the Java platform provides synchronization (monitor) locks, the synchronized keyword, and classes like Thread  and ThreadGroup to make the multithreaded programmer's life more productive and less error-prone.
Q . How do I create a thread and start it running?

Ans : 

Create an instance of Thread or of a Thread subclass, and invoke start on that instance.

     The Java programming language and virtual machine represent threads with instances of the Thread class. At the heart of every thread is a run method, which determines the body of code the thread will execute in its lifetime. The Thread class provides two ways to specify what run method the thread will execute:

  • define a run method in a Thread subclass
  • adopt the run method of an object that implements the Runnable interface
The first approach is to subclass Thread and override its run method. This approach is more straightforward, and works best when the data needed for running the thread is fairly self-contained. At a minimum, you can define a subclass of Thread with nothing more than a new run method. The following Thread subclass, for example, represents a thread of execution that can print out the square roots of integers from 1 to 1,000,000:
     public class SquareRootThread extends Thread {
         public void run() {
             for (int i = 1; i <= 1000000; ++i) {
                 System.out.println("Math.sqrt(" + i + ") = "
                                    + Math.sqrt(i));
             }
         }
     }
This class definition merely specifies what the thread can do. To execute the thread's code, you create an instance of the class and invoke start on it:
     Thread t1 = new SquareRootThread();
     t1.start();
Invoking start on a Thread instance starts a new, separately scheduled thread in the Java Virtual Machine, which then executes the code specified in the run method of that Thread subclass.
     The second approach, using the Runnable interface, is less direct but often more useful. A new Thread instance can be created based on any object from a class that implements the Runnable interface. A Runnable object must include a definition for a run method that takes no parameters and has no return value: public void run() { /* ... */ }.
     A Thread instance created from a Runnable object takes the run method of that object's class as its own code to execute. For example, Applet subclasses are commonly defined to implement Runnable so that their run methods can execute in a separate thread:
     public class MyApplet extends java.applet.Applet
                           implements Runnable {
         public void run() {
             doThis();
             doThat();
         }
         // ...
     }
You can create an instance of the Thread class using the Thread(Runnable) constructor. Once you have the Thread instance, you start it just like any other thread:
     // ... "this" refers to the current applet instance
     Thread t2 = new Thread(this);
     t2.start();
     A primary reason to create a thread from a Runnable object is to take advantage of full insider access to that object. Inside an applet, a run method has direct access to all the applet's data and methods. A Thread subclass, on the other hand, would be limited to only an outsider's view of the applet, which is typically just the public methods. In short, if your thread depends strongly on a certain object for its execution, you should should define that object's class to implement the Runnable interface, and construct a Thread instance from the object.
Q . How many threads can I create?

Ans : 

By default, on a Win32 machine, each ("native") thread gets one MB (1024*1024 bytes) of stack space reserved for it. The memory is not actually allocated. If it were, you'd run out of memory with dozens of
threads instead of hundreds. The space needs to be reserved as a contiguous block of memory so the stack can grow as needed.

Under Win32, the max amount of memory is 2GB, which corresponds to 2,000 threads each reserving 1MB of memory. That's an upper bound; in practice you'd run out of other OS resources before running out of memory. Each thread has some system resources that will be used to manage the thread -- register storage area, thread-local storage, state information, exception condition info, etc.

You should design your programs so that you use threads only where necessary. It's almost always a mistake to have one thread per object. Successful programs are much more likely to have 5 threads (or fewer) than 500.

Q . How does Thread's stop method work--can I restart a stopped thread?

Ans : 

Thread's stop method stops a thread permanently—that thread cannot be run again.

     A Thread instance has three main phases in its existence:

  1. prebirth: creation and configuration, before being started
  2. life: execution of code, after being started and before terminating
  3. death: postmortem, after terminating, but before being garbage collected
     Creating and starting a Thread instance  brings a thread to life. A thread continues to execute code until it reaches the end of its run method or until stop is invoked on it. The Thread class's stop method could just as well be named kill or terminate. The method is not a hint, but a command—it irrevocably ends the execution phase of the thread. The thread may not die immediately, because it is in a sleep or a wait, but in that case it is fated to die as soon as it awakes. Also, any synchronization locks  held by the terminated thread are automatically released. Once the Thread instance has reached this postmortem phase, you can no longer run code with it; you can only inspect its state.
     Restarting a stopped thread is not possible, but you can achieve much the same effect by creating a new Thread instance to run the same code
Q . If I create a thread, and then null out the reference to it, what happens to the thread? Does it get interrupted or what?

Ans :  

The code looks like this:

      Thread t = new Thread( my_runnable_obj );
      t.start();
         ...
      t = null; // what happens to the thread?

The answer is that you may no longer have a reference to the thread, but the JVM still does. Once a thread is started, and as long as it keeps running, it is a root object. Root objects are the starting
points for "things in use" that the garbage collector uses.

Q . How should I stop a thread so that I can start a new thread later in its place?

Ans : 

Use the cooperative approach wherever possible: set a flag to indicate that the thread should stop, but let the targeted thread itself check for the flag and find a safe place to stop.

     Early Java programs commonly used Thread's stop method to terminate threads, especially in applet start and stop methods. For example:

     /* common in applets, but NOT recommended: */
     Thread myThread;
     public void start() {
         if (myThread == null) {
             myThread = new Thread(this);
         }
         myThread.start();
     }

     public void stop() {
         myThread.stop();
         myThread = null;
     }
     This technique is simple but dangerous! Invoking stop on a thread is analogous to killing a process without warning: execution ceases, but there are no guarantees about what state the program is left in. Moreover, if another Thread instance is created to continue execution where the previous thread left off, an inconsistent state left by the earlier thread can inflict serious damage on your program.
     In general, you should design your program so that a running thread can choose a safe place to stop itself. It's best to save the stop method for cases when you truly need to terminate an uncooperative thread. (While on the topic of methods to avoid, note also that suspend and resume are considered dangerous, or downright evil, by many Java developers.)
     In normal cases, several conditions are desirable when starting and stopping a thread for an applet:
  • Only one thread at a time can be running the applet code.
  • Invoking start on the applet either starts a new thread for the applet or lets an existing thread continue running.
  • Invoking stop on the applet registers a request that the running thread stop; a subsequent invocation of start can cancel that request.
The following code framework meets the conditions just specified:
     boolean stopRequested = false;
     Thread myThread;
     /** Starts new thread for applet if applet doesn't have one. */
     public synchronized void start() {
         if (myThread == null) {
             myThread = new Thread(this);
             myThread.start();
         }
         stopRequested = false;
     }

     /** Requests that this applet stop its activity. */
     public synchronized void stop() {
         stopRequested = true;
     }

     /** Runs applet code in its own thread. */
     public void run() {
         // ... thread activity
         /* At safe stopping point, check if thread should quit: */
         synchronized (this) {
             if (stopRequested) {
                 // ... perform any quick cleanup necessary
                 stopRequested = false;
                 myThread = null;
                 return;  // returning from run finishes current thread
             }
         }
         // ... further thread activity and flag checks
         }
     }  // reaching end of run finishes current thread
Q . How do I specify pause times in my program?

Ans : 

Use one of the sleep methods in the Thread class.

     The Thread class's sleep methods let you time a thread's activities, or simply wait for a while, without wasting system resources. In the more commonly used version, you specify the number of milliseconds (thousandths of a second) that the current thread should cease execution. For example, to pause half a second between two portions of code, you could write:

     // ... code before the pause
     try {
         Thread.sleep(500);
     } catch (InterruptedException e) {
         // ... handle exception
     }
     // ... code after the pause
Note that sleep can throw an InterruptedException, which your code must handle or explicitly ignore.
     The sleep methods are class methods —they belong to the Thread class but are not invoked on any particular Thread instance. Nevertheless, a sleep method knows which thread to pause: the thread that is currently executing.
     Note: The wait methods in class Object provide an important alternative way to control a thread's pauses

 

Copyright © 2000 javafaq.com. All rights reserved