ZeePedia

JAVA: Multithreading 1

<< JAVA: Serialization
JAVA: Multithreading 2 >>
img
Web Design & Development ­ CS506
VU
Lesson 23
Multithreading
Introduction
Multithreading is the ability to do multiple things at once with in the same application. It provides finer
granularity of concurrency. A thread -- sometimes called an execution context or a lightweight process --
is a single sequential flow of control within a program.
Threads are light weight as compared to processes because they take fewer resources then a process. A
thread is easy to create and destroy. Threads share the same address space
i.e. multiple threads can share the memory variables directly, and therefore may require more complex
synchronization logic to avoid deadlocks and starvation.
Sequential Execution vs Multithreading
Every program has atleast one thread. Programs without multithreading executes sequentially. That is, after
executing one instruction the next instruction in sequence is executed. If a function is called then until the
completion of the function the next instruction is not executed. Similarly if there is a loop then instructions
after loop only gets executed when the loop gets completed. Consider the following java program having
three loops in it.
// File ThreeLoopTest.java
public class ThreeLoopTest {
public static void main (String args[ ]) {
//first loop
for (int i=1; i<= 5; i++)System.out.println("first " +i);
// second loop
for (int j=1; j<= 5; j++)System.out.println("second " + j);
// third loop
for (int k=1; k<= 5; k++)System.out.println("third " + k);
} // end main} // end class
Note: Each loop has 5 iterations in the ThreeLoopTest program.
168
img
Web Design & Development ­ CS506
VU
Note: Each loop has 10 iterations in the ThreadTest program. Your output can be different from
the one given above.
Notice the difference between the outputs of the two programs. In ThreeLoopTest each loop generated a
sequential output while in ThreadTest the output of the loops got intermingled i.e. concurrency took place
and loops executed simultaneously
Let us code our first multithreaded program and try to learn how Java supports multithreading.
Java includes built-in support for threading. While other languages have threads bolted-on to an existing
structure. i.e. threads were not the part of the original language but latter came into existence as the need
arose.
All well known operating systems these days support multithreading. JVM transparently maps Java
Threads to their counter-parts in the operating system i.e. OS Threads. JVM allows threads in Java to take
advantage of hardware and operating system level advancements. It keeps track of threads and schedules
them to get CPU time. Scheduling may be pre-emptive or cooperative. So it is the job of JVM to manage
different tasks of thread. Let's see how we can create threads?
Creating Threads in Java
There are two approaches to create threads in Java.
Using Interface
Using Inheritance
Following are the steps to create threads by using Interface:
1
Create a class where you want to put some code that can run in parallel with some other code and
let that class implement the Runnable interface
2
Runnable interface has the run() method therefore provide the implementation for the run() method
and put your code that you want to run in parallel here
169
img
Web Design & Development ­ CS506
VU
3
Instantiate Thread class object by passing Runnable object in constructor
4
Start thread by calling start() method
Following are the steps to create threads by using Intheritance:
1
Inherit a class from java.lang.Thread class
2
Override the run() method in the subclass
3
Instantiate the object of the subclass
4
Start thread by calling start() method
To write a multithreaded program using Runnable interface, follow these steps:
·  Step 1 - Implement the Runnable Interface
class Worker implements Runnable
·  Step 2 - Provide an Implementation of run() method
public void run( ){// write thread behavior// code that will be executed by the thread
·  Step 3 - Instantiate Thread class object by passing Runnable object in the constructor
Worker w = new Worker("first");
Thread t = new Thread (w);
·
Step 4 ­ Start thread by calling start() method
t.start();
Threads Creation Steps Using Inheritance
To write a multithreaded program using inheritance from Thread class, follow these steps:
Step 1 ­ Inherit from Thread Class
class Worker extends Thread
Step 2 - Override run() method
public void run( ){
// write thread behavior
// code that will execute by thread
Step 3 - Instantiate subclass object
Step 4 ­ Start thread by calling start() method
Worker w = new Worker("first");
t.start();
So far we have explored:
What is multithreading?
What are Java Threads?
Two ways to write multithreaded Java programs
Now we will re-write the ThreeLoopTest program by using Java Threads. At first we will use the Interface
approach and then we will use Inheritance.
Code Example using Interface
// File Worker.java
public class Worker implements Runnable {
private String job ;
//Constructor of Worker class
public Worker (String j ){
job = j;
}
//Implement run() method of Runnable interface
public void run ( ) {
for(int i=1; i<= 10; i++)System.out.println(job + " = " + i);
170
img
Web Design & Development ­ CS506
VU
}
} // end class
// File ThreadTest.java
public class ThreadTest{
public static void main (String args[ ]){
//instantiate three objects
Worker first = new Worker ("first job");
Worker second = new Worker ("second job");
Worker third = new Worker ("third job");
//create three objects of Thread class & passing worker
//(runnable) to them
Thread t1 = new Thread (first );
Thread t2 = new Thread (second);
Thread t3 = new Thread (third);
//start threads to execute
t1.start();
t2.start();
t3.start();
}//end main} // end class
Following code is similar to the code given above, but uses Inheritance instead of interface
// File Worker.java
public class Worker extends Thread{
private String job ;
//Constructor of Worker class
public Worker (String j ){
job = j;
}
//Override run() method of Thread class
public void run ( ) {for(int i=1; i<= 10; i++)System.out.println(job + " = " + i);
}
} // end class
// File ThreadTest.java
public class ThreadTest{
public static void main (String args[ ]) {
//instantiate three objects of Worker (Worker class is now
//becomes a Thread because it is inheriting from it)class
Worker first = new Worker ("first job");
Worker second = new Worker ("second job");
Worker third = new Worker ("third job");
//start threads to execute
t1.start();
t2.start();
t3.start();
}//end main} // end class
Threads provide a way to write concurrent programs. But on a single CPU, all the threads do not run
simultaneously. JVM assigns threads to the CPU based on thread priorities. Threads with higher priority are
executed in preference to threads with lower priority. A thread's default priority is same as that of the
creating thread i.e. parent thread.
A Thread's priority can be any integer between 1 and 10. We can also use the following predefined
constants to assign priorities.
171
img
Web Design & Development ­ CS506
VU
Thread.MAX_PRIORITY (typically 10)
Thread.NORM_PRIORITY (typically 5)
Thread.MIN_PRIORITY (typically 1)
To change the priority of a thread, we can use the following method
setPriority(int priority)
It changes the priority of this thread to integer value that is passed. It throws an IllegalArgumentException
if the priority is not in the range MIN_PRIORITY to MAX_PRIORITY i.e. (1­10).
For example, we can write the following code to change a thread's priority.
Thread t = new Thread (RunnableObject);
// by using predefined constantt.setPriority
(Thread.MAX_PRIORITY);
// by using integer constantt.setPriority (7);
Thread Priority Scheduling
The Java runtime environment supports a very simple, deterministic scheduling algorithm called fixed-
priority scheduling. This algorithm schedules threads on the basis of their priority relative to other
Runnable threads.
At any given time, when multiple threads are ready to be executed, the runtime system chooses for
execution the Runnable thread that has the highest priority. Only when that thread stops, yields (will be
explained later), or becomes Not Runnable will a lower-priority thread start executing. If two threads of the
same priority are waiting for the CPU, the scheduler arbitrarily chooses one of them to run. The chosen
thread runs until one of the following conditions becomes true:
A higher priority thread becomes Runnable.
It yields, or its run() method exits.
On systems that support time-slicing, its time allotment has expired.
Then the second thread is given a chance to run, and so on, until the interpreter exits. Consider the
following figure in which threads of various priorities are represented by capital alphabets A, B, ..., K. A
and B have same priority (highest in this case). J and K have same priority (lowest in this case). JVM start
executing with A and B, and divides CPU time between these two threads arbitrarily. When both A and B
comes to an end, it chooses the next thread C to execute.
Code Example: Thread Properties
Try following example to understand
how JVM executes threads based on
their priorities.
// File PriorityEx.java
public class PriorityEx{ public static
void main (String args[ ]){
//instantiate two objects
Worker first = new Worker
("first job");
Worker second = new Worker
("second job");
//create two objects
Thread t1 = new Thread (first );
Thread t2 = new Thread
(second);
//set thread priorities
t1.setPriority
172
img
Web Design & Development ­ CS506
VU
(Thread.MIN_PRIORITY);
t2.setPriority (Thread.MAX_PRIORITY);
//start threads to execute
t1.start();
t2.start();
}//end main} // end class
Output
Problems with Thread Priorities
However, when using priorities with
Java Threads, remember the following
two issues:
First a Java thread priority may map
differently to the thread priorities of
the underlying OS. It is because of
difference in priority levels of JVM
and underlying OS. For example
32
Solaris has 2 ­1 priority
levels
Windows NT has only 7 user
priority levels
Second, starvation can occur for
lower-priority threads if the higher-priority threads never terminate, sleep, or wait for I/O indefinitely.
173
img
Web Design & Development ­ CS506
VU
References:
Java, A Practical Guide by Umair Javed
Java How to Program by Deitel and Deitel
CS193j handouts on Stanford
174