Anda di halaman 1dari 11

Threading in Java NIIT 87

Threading in Java
Objectives
At the end of this period, you will be able to: Define a thread. Understand the difference between Multitasking and Multithreading. Implement threads in Java. Understand the life cycle of a thread. Create a simple thread class. Create an extended thread class. Create a runnable thread class. Work with multiple threads. Understand the usage of garbage collection.

Introduction
Definition of a Thread
A thread can be defined as a separate set of program that can be planned to be executed by the operating system .This program will get executed simultaneously and independently of any other program. Without threads an entire program can be held up by one CPU intensive task or one infinite loop. With threads the other tasks that don't get stuck in the loop can continue processing without waiting for the stuck task to finish. It turns out that implementing threading is harder than implementing multitasking in an operating system. The reason it's relatively easy to implement multitasking as individual programs are isolated from each other, however, individual threads are not. For example if printing is happening in one thread, but the user deletes a large chunk of text in another thread. What's printed? The document as it was before the deletion? Or the document as it was after the deletion? The document with some but not all of the deleted text? Or does the whole system crash? Most often in a non-threaded or poorly threaded system it's the latter. Threaded environments like Java allow a thread to put locks on shared resources so that while one thread is using data no other thread can touch that data. This is done with synchronization. Synchronization should be used sparingly since the purpose of threading is defeated if the entire system gets stopped waiting for a lock to be released. The proper choice of objects and methods to synchronize is one of the more difficult things to learn about threaded programming.

Multitasking Vs Multithreading
Operating systems that allow multiple people to use expensive computer at the same time is multitasking. Multiple people work on different applications on a time sharing basis is also multitasking. In time sharing concept the operating system splits the time among the different programs that are running. Once Operating systems allowed different users to run programs at the same time it was a short step to letting the same user run multiple programs simultaneously. Each running
Threading in Java 88 NIIT

program (generally called a process) had its own memory space, its own set of variables, its own stack and heap, and so on. There are multiple processes and each process runs independently of others. It cannot access the data of other processes. The resources for the particular process are allotted through the Operating system. For example, memory and CPU.

One process could spawn another process, but once that occurred the two processes behaved more or less independently. Mechanisms like remote procedure calls (RPC) were developed to allow processes to interact with each other, but such interaction was expensive and difficult. This is the drawback of multitasking. To overcome this draw back threads where invented. It is not just users that want to do different things at the same time, many programs also need to do several things at once. A web browser, for instance, can print a file in the background while it downloads a page in one window and formats the page as it downloads. The ability of an individual program to do more than one thing at the same time is most efficiently implemented through threads. Threads have their own call stack but can access the shared data. Every thread has its own memory cache. The data read from the shared data is stored in its own memory cache. A thread can re-read the shared data. This can be implemented in Java threads.

Threads in Java
Java applications and applets are naturally threaded. The runtime environment starts execution of the program with the main() method in one thread. Garbage collection takes place in another thread. Screen updating occurs in a third thread. There may be other threads running as well, mostly related to the behavior of the applet viewer or web browser. All of this happens invisibly to the programmer. Some of the time you're only concerned with what happens in the primary thread which includes the main() method of a program. If this is the case you may not need to worry about threading at all. Sometimes, however, you need to add your own threads to an applet or application. The simplest reason for adding separate thread is to perform a long calculation. For instance if you're trying to find the ten millionth prime number, you probably don't want to make users twiddle their thumbs while you search or you may be waiting for a resource that isn't available yet, for example, a large graphic to download from the Internet. Once again you shouldn't make the user wait while your program waits. Any operation that is going to take a noticeable period of time should be placed in its own thread. The other reason to use threading is to more evenly divide the computer's power among different tasks. If you want to draw random rectangles on the display, you would still like the applet to respond to user input. If all the CPU time is spent drawing rectangles, there's nothing left over for the user. On a preemptively multitasking operating system like Solaris or Windows NT, the user may at least be able to kill the application. On a cooperatively multitasking operating system like the MacOS or Windows, the user may have to reboot their machine. This is a bad thing. With threads you can set the priority of different processes, so that user input receives a high priority and drawing pretty pictures receives a low priority. Then the user can stop the applet without flipping the power switch on their machine.
Threading in Java NIIT 89

Figure 5.1: Multiple processes in Java

Life Cycle of a Thread


Following is the life cycle of a thread: Cycle State Description Start New instance of a thread Runnable Thread Starts Running Thread receives the process time Dead Thread completes its execution or has encountered an exception Block Thread stops execution due to insufficient memory and returns to the run state Deadlock Two threads get locked and program stops execution Waiting Thread waits for some user intervention or something to happen, the

thread once again moves to the Runnable state Sleeping Thread sleeps, after the time allotted for sleeping passed, the thread automatically return to the Runnable state and starts executing.
Table 5.1: Life Cycle of a Java Thread

The following figure is the diagrammatic representation of the life cycle of a thread.
Figure 5.2: Life Cycle of a Java Thread CPU
Threading in Java 90 NIIT

Thread class in Java


Threading is implemented in a program in two ways. 1. Create a subclass of java.lang.Thread. 2. By using java.lang.Runnable interface. This process is used when you want to thread an object that's already a subclass of another class. The following are the thread methods: Methods Description start() The start() method prepares a thread to run run() The run() method actually performs the work of the thread wait() The thread is in the waiting state yield() This pauses the running thread and allows the other threads to run sleep() The thread is transited to sleep for a specified amount of time interrupts() Interrupts the running thread and transits it to the runnable state setPriority() Sets the priority of a thread stop() The stop() method halts the thread. The thread dies when the run() method terminates or when the thread's stop() method is invoked
Table 5.2: Methods used in Java thread

The three primary methods that are used to control a thread are: public native synchronized void start() public void run() public final void stop() You never call run() explicitly. It is called automatically at runtime as necessary once you've called start(). The Runnable interface allows you to add threading to a class which, for one reason or another, cannot conveniently extend Thread. It declares a single method, run(): public abstract void run() By passing an object which implements Runnable to a Thread() constructor, you can substitute the Runnable's run() method for the Thread's own run() method. (More properly the Thread object's run() method simply calls the Runnable's run() method.) Syntax
class <className> extends Thread { Variable Type Name; constructor(); { // java statements; } }
Threading in Java NIIT 91

Create threads by extending the thread class


When writing a threaded program you can think that you're writing many different programs, each with its own run() method. Each thread is a subclass of java.lang.Thread. The following program is a thread that prints the numbers between -100 and 100.

public class ByteThread extends Thread { public void run() { for (int c = -100; c <100; c++) { System.out.println(c); } } }

Save this file as ByteThread.java. You launch this thread from another method, probably in another class, by instantiating an object of this class using new and calling its start() method. To create a thread just call the default constructor for your subclass of Thread. For instance
ByteThread bt = new ByteThread();

Simple thread Class


The following program launches a single ByteThread thread:
public class ThreadExecution { public static void main(String args[]) { System.out.println("The thread construction..."); ByteThread bt = new ByteThread(); System.out.println("Thread is ready to start..New thread"); bt.start(); System.out.println("The thread has been started."); return; } }

Save this file as ThreadExecution.java. Compile the ByteThread.java file first. Then compile the ThreadExecution.java file and execute the ThreadExecution java file. Example The following example illustrates the usage of threads in one single program. The easiest thread program can be created using the run() method. The set of java statements can be written within the run() method.
public class D extends Thread { String title;
Threading in Java 92 NIIT

public D(String output, int delay) { title = output; } public void run ( ) // run method { try { for(;;){ System.out.println(title + " "); Thread.sleep(10); System.out.println("Will exit from the thread now); } } catch(InterruptedException x) { return;

} } public static void main (String[] arguments){ new D("D", 10).start( ); new D("G", 25).start( ); System.exit(0); } }

In the sample program given the thread will first print the message, then sleep for 10 seconds and then exit from the thread. To exit from the thread you have to include System.exit(0) in the main method. If this is omitted then the thread will never terminate. You can increase the sleep time of the thread and check for the output. The output of the sample program is given below.
Figure 5.3: Output of the Sample Code

The output may vary depending on the operating system.


Threading in Java NIIT 93

Creating threads by using runnable interface


The thread created remains active as it is created using the runnable interface. The runnable interface defines rules for the thread. The class created using runnable interface will have a run method which will not have any arguments. Example
public class runnab implements Runnable { Thread t; public runnab(String s) { t = new Thread(this, s); t.start(); } public void run() { for (int a = 1; a <= 5; a++) { System.out.println(a + " Parent " + Thread.currentThread().getName()); // currentthread() is a method of the thread class } } public static void main(String[] args) { runnab r = new runnab("Child"); for (int a = 1; a <= 5; a++) { System.out.println(a + " From " + Thread.currentThread().getName()); } } }

In the sample code given above a parent and child thread are created. The run() method is a parent thread and when the main() method is executed first a message, Child is displayed. The main method gets executed first and a thread is created, which is called Child. In the subsequent loop the run() method gets executed. The thread number and the message Parent gets displayed along with the message, Child from the main method.
Threading in Java

94 NIIT

Figure 5.4: Output of the Sample Code

The output may vary depending on the operating system. The main difference in creating threads using runnable interface and extends thread is, thread is a class and runnable is an interface. The following program uses a runnable thread class which has to be saved as thread.java and compiled. Example
class thread implements Runnable { String name; // name of thread Thread t; thread(String threadname) { name = threadname; t = new Thread(this, name); System.out.println("New thread: " + t); t.start(); // Start the thread } // Entry point for thread public void run() { try { for(int i = 5; i > 0; i--) { System.out.println(name + ": " + i); Thread.sleep(1000); } } catch (InterruptedException e) { System.out.println(name + " interrupted."); } System.out.println(name + " exiting.");
Threading in Java NIIT 95

} }

Suspend and Resume threads


The suspend() method temporarily halts a running thread. The resume() method picks up execution of the thread where it left off. Syntax
public final void suspend () public final void resume ()

isAlive and Join


There are two methods to determine whether a thread has completed its execution.
isAlive() and join() methods. isAlive(): This method is defined by Thread.

Syntax
final boolean isAlive();

If the thread is still running then the isAlive( ) method returns true, else it returns false. The commonly used method to complete the execution of the thread is called join( ). Syntax
final void join( ) throws InterruptedException

This method waits until the thread on which it is called completes its execution. The following sample code will illustrate how the join and alive methods are used in threading.

A sample program which uses join() and isAlive() methods is given, save this file as threadjoin.java.
class threadjoin { public static void main(String args[]) { thread ob1 = new thread("First"); thread ob2 = new thread("Second"); thread ob3 = new thread("Third"); System.out.println("First thread is alive: " + ob1.t.isAlive()); System.out.println("Second thread is alive: " + ob2.t.isAlive()); System.out.println("Third thread is alive: " + ob3.t.isAlive()); // wait for threads to terminate try { System.out.println("Waiting for threads to terminate.");
Threading in Java 96 NIIT

ob1.t.join(); ob2.t.join(); ob3.t.join(); } catch (InterruptedException ev) { System.out.println("Main thread Interrupted"); } System.out.println("First thread is alive: " + ob1.t.isAlive()); System.out.println("Second thread is alive: " + ob2.t.isAlive()); System.out.println("Third thread is alive: " + ob3.t.isAlive()); System.out.println("Quitting the main thread"); } }

Steps to work with the sample program given above. 1. Compile the thread.java file first. 2. Compile the threadjoin.java file. 3. Execute the threadjoin file. In the sample program given above, there are two java files. The first java file is the thread.java file which has been created using the runnable interface. The second java file (threadjoin.java) has code where it calls the threads created in the first java file(thread.java). Hence when the threadjoin file is executed it calls the thread created in the thread.java file. In the sample program given above three threads are created. In the threadjoin.java file isAlive() and join() methods are used to check whether the thread is alive or terminated. Exceptions are caught in the try and catch block.

Multiple threads
You can create multiple threads of the same program. Each thread will run in different processes. The sample program illustrates the usage of multiple threads.
public class ThreadE {

public static void main(String args[]) { System.out.println("Constructing the thread..."); ByteThread bt1 = new ByteThread(); ByteThread bt2 = new ByteThread();
Threading in Java NIIT 97

ByteThread bt3 = new ByteThread(); System.out.println("Starting the thread..."); bt1.start(); bt2.start(); bt3.start(); return; } }

To execute the sample program given above, you have to compile the ByteThread.java program given above first. Then compile, execute the ThreadE.java file. In the sample code given three threads are created in the first program (ByteThread.java). Another way of working with multiple threads is by creating two java files. One file will consist of thread class by using runnable interface. Another file will have code where multiple threads are created for the first java file. Example Sample code for creating multiple threads by using the runnable interface is given below. The first java file given below, referred to as, (M.Java) will print the heading for 5 times and sleep for 1000 seconds.
class M implements Runnable { String heading; Thread t; M(String display) { heading= display; t = new Thread(this, heading); //this keyword used to refer to the current object System.out.println("New thread: " + t); t.start(); // Start the thread } public void run() { try { for(int i = 5; i > 0; i--) { System.out.println(heading + ": " + i); Thread.sleep(1000); } } catch (InterruptedException e) { System.out.println(heading + "Interrupted");
Threading in Java 98 NIIT

} System.out.println(heading + " exiting."); } }

The file, M.java has to be compiled first. Given below is a sample code for the second java file. This is referred to as, MultiThread.java. This file creates a new instance of the, M.class file.

class MultiThread { public static void main(String args[]) { new M("One"); // start threads. Has created the new instance of the M class which is the base template new M("Two"); new M("Three"); try { // wait for other threads to end Thread.sleep(1000); } catch (InterruptedException e) { System.out.println("Main thread Interrupted"); } System.out.println("Main thread exiting."); } }

Compile the MultiThread.java file and execute it. Observe that the heading message is printed first as the base class is called, and then the message of the derived class is printed.
Figure 5.5: Multiple threads
Threading in Java NIIT 99

Thread Synchronization
While a program runs multiple threads, different ways are required for synchronizing the methods. When there are two or more threads which share common code problems, inconsistency in data happens. When the code is synchronized at a given time only one thread will have rights to access that code. Other threads will not be able to access the code, till the shared code is freed. To synchronize the threads Java uses monitor. Monitor is a mechanism which holds only one thread. When a thread enters monitor, the other threads have to wait. Each object in Java has its own implicit monitor. Once a thread is inside a synchronized method no other thread can call any other synchronized method on the same object. This avoids deadlock. To make a method synchronize, add the synchronized keyword before the method as shown below:
public synchronized void increment() { c++; } public class SychronizedCounter extends Counter { public synchronized void count() { int limit = i + 100; while (i++ != limit) System.out.println(i); } }

Constructors cannot be synchronized. Using the keyword synchronized with a constructor will throw a syntax error.

Deadlock
Deadlock occurs in multiple threads. This happens when there is a circular dependency of threads and each thread holds synchronization lock while waiting for another. The lock each thread waits for is held by another thread. Deadlock occurs rarely.

Thread Priorities
All threads cannot be given equal time. Sometimes you want to give one thread more time

than another. Threads that interact with the user should get very high priorities. On the other hand threads that calculate in the background should get low priorities. Thread priorities are defined as integers between 1 and 10. Ten is the highest priority. One is the lowest. The normal priority is five. Higher priority threads get more CPU time. Thread defines three mnemonic constants, Thread.MAX_PRIORITY, Thread.MIN_PRIORITY and Thread.NORM_PRIORITY which you can use in place of the numeric values. You set a thread's priority with the setPriority(int priority) method.
Threading in Java 100 NIIT

Garbage Collection
In a java program, objects are dynamically allocated using new operator. Some of the objects may not be used in the program. Unused objects occupy the memory. Unused objects within the source code are collected automatically in Java. This is called garbage collection. The objective of the garbage collection is: To allocate memory when it is needed by the program. To reclaim that memory when it is no longer needed, and To reuse it as appropriate. Failure to deal with this important issue results in a condition often referred to as "memory leakage." The garbage collector is a part of the runtime system that runs in a low-priority thread reclaiming memory that is no longer needed by objects used by the program. An object becomes eligible for garbage collection in Java when there are no longer any reference variables that reference the object. In Java, you can have one or more reference variables which reference the same object. That object will not become eligible for garbage collection until all of those reference variables go out of scope, are assigned to a different object, or are assigned a value of null. The disadvantage of garbage collection is that it would require more CPU time. This will affect the performance time of the program. In Java the garbage collection is done by invoking a method. The steps involved in using a garbage collector are: 1. Create a java runtime object. The runtime object is an interface with the Java environment. 2. Invoke the created object.

Syntax
Runtime variable_name = Runtime.getruntime(); // Runtime object variablename.gc(); // invoking the runtime object

Example
public class Garbage { final int N = 60000; void eMemory() { int[] A = new int[N]; for (int i=0; i<N; i++) { A[i] = i; } }
Threading in Java NIIT 101

public static void main (String[] args) {

Garbage g = new Garbage(); // Create and get a Runtime object Runtime r = Runtime.getRuntime(); // Find the current amount of free memory long fMem = r.freeMemory(); System.out.println("Free memory before creating an array: " + fMem); // Memory consumed g.eMemory(); // Find the amount of memory left after consumption fMem = r.freeMemory(); System.out.println("Free memory after creating array: " + fMem); // Invoke the garbage collector to check free Memory r.gc(); fMem = r.freeMemory(); System.out.println("Free memory after executing the garbage collector: " + fMem); } }

The figure shown is the output of the example code given.


Figure 5.6: Garbage Collection

Now You Know


Threads are set of program scheduled to get executed by an Operating system. Multitasking is multiple people working on different applications on a time sharing basis. The ability of an individual program to do more than one thing at the same time is most efficiently implemented through threads. Java applications and applets are naturally threaded. In multiple threads each thread will run in different processes. Monitor is a mechanism which holds only one thread. The suspend() method temporarily halts a running thread. Deadlock occurs when there is a circular dependency of threads. The collection of unused objects within the java source code is called garbage collection.