At the end of this chapter, you will be able to understand and use
Many of you would have come across a pop-up while you are using the Internet or operating system, wherein the pop message would say “OS or Browser has experienced a serious problem and needs to be closed down. Error reporting is in process”. Indeed, an error has occurred. Despite elaborate testing prior to delivery, errors cannot be prevented, but they can be minimized. In this chapter, we will study the mechanism of Java to handle errors and exceptions.
An important and innovative feature of Java programming is multithreaded programming. Just as Operating System manages several processes concurrently and schedules the next process CPU should handle, Java provides multithreaded programming wherein we can create several concurrent threads and manage thread scheduling at programmer's level. The advantage is that more than one thread process can be running at the same time albeit with different priorities.
Errors that crop up in a program are of three types:
Exceptions, on the other hand, are unusual conditions that occur at run time and can lead to errors that can crash a program. The exceptions can be classified as:
Synchronous are those that can be predicted. For example, array index going outside the permissible values can be easily detected because such errors occur only when you have executed the statement involving array index. The synchronous exception can occur at any one or more of the following situations:
Asynchronous exceptions are those that cannot be predicted. Generally, the resources required for the program are allocated at the very beginning of the program and resources are demanded at run time. Thus, it is likely that our program may exceed the initial allotment. As an example, consider allocated memory for an array. When such an exception occurs, we need a mechanism to carry such information to an area where recourses are allocated so that we can take corrective actions and prevent the program from crashing.
The exceptions that are checked by compiler are called checked exceptions. Example: public static void main(String [] args) throws IOException.
The exceptions checked by JVM at run time are called unchecked exceptions. All exceptions and errors are objects in Java. These objects are derived from the package java.lang. Throwable shown in Figure 20.1.
Figure 20.1 Exception class hierarchy
Figure 20.2 Try and catch blocks in exception handling mechanism
The most likely area for exceptions to occur is where resources are allocated or where input and output programming is involved. These are listed in Table 20.1.
Java Exception | Remarks |
---|---|
Arithmetic Exceptions | Divide by zero and other mathematical exceptions |
ArrayIndexOutOfBoundsException | Index going out of originally defined dimension |
FileNotFoundException | File not existing |
IOException | Caused by IO statements |
NullPointerException | Reference to a null object |
NumberFormatException | Occurs when conversion from number to String fails |
OutOfMemoryException | Memory limits exceeded |
StackOverFlowException | Stack over flow |
StringOutOfBoundsException | Occurs when limit of String definition is exceeded |
Java raises an exception object. For it to do so, we need to use a try block wherever we expect likely exception. Catch block that follows the try block catches the exception object and takes remedial action.
1. package com.oops.chap20;
2. import java.util.*;
3. class MatrixAlloc {
4. void ReadMat(int A[][],int rows, int cols){
5. //input matrix related data using scanner
6. Scanner scn=new Scanner(System.in);
7. for ( int i=0;i<rows;i++)
8. for ( int j=0;j<cols;j++)
9. A[i][j]=scn.nextInt();
10. }
11. void DisplayMatrix(int A[][],int rows, int cols){
12. for ( int i=0;i<rows;i++)
13. {for ( int j=0;j<cols;j++)
14. { System.out.print( A[i][j] +” “);}
15. System.out.print( “
”);}
16. }//end of DisplayMatrix
17. void AddMat(int A[][],int B[][],int rows, int cols){
18. for ( int i=0;i<rows;i++)
19. {for ( int j=0;j<cols;j++)
20. System.out.print( (A[i][j]+B[i][j]) +” “);
21. System.out.print( “
”);}
22. }//end of TranspMat
23. }//end of MatrixAlloc
24. class TwoDMatrix{
25. public static void main(String[] args)
26. {try{
27. Scanner scn = new Scanner(System.in);
28. MatrixAlloc obj=new MatrixAlloc();
29. System.out.print(“Enter no of rows & columns:”);
30. int rows= scn.nextInt();
31. int cols= scn.nextInt();
32. int A[][]= new int[rows][cols];
33. int B[][]= new int[rows][cols];
34. MatrixAlloc mat = new MatrixAlloc();
35. System.out.println(“Enter Data for Matrix A”);
36. obj.ReadMat( A ,rows,cols);
37. System.out.println(“Enter Data for Matrix B”);
38. obj.ReadMat( B ,rows,cols);
39. System.out.println(“Addition of two Matrices”);
40. mat.AddMat(A,B,rows, cols);
41. } catch( Exception e){};
42. }
43. } //end of MatTranspose
OUTPUT : Enter no of rows & columns:2 2
Enter Data for Matrix A 10 20 30 40
Enter Data for Matrix B 10 20 30 40
Addition of two Matrices
20 40
60 80
Line No. 26: | shows that we have included try { block which will extend up to Line No. 41 which is catch block. We have put a try block because we have memory allocation at Line Nos. 27 & 28 : Scanner scn = new Scanner(System.in);MatrixAlloc obj=new MatrixAlloc(); Line No. 32 & 33 allocate memory to matrices A and B. |
Line No. 41: | catches Exception e. Of course no further action is planned as indicated by {} |
In our next example, we will show Arithmetic type of exception called divide by zero exception.
Example 20.2: DiveByZero.java A Program to Show Divide by Zero Exception
1. package com.oops.chap20;
2. import java.util.*;
3. public class DivideByZero {
4. public static void main(String[] args) {
5. double mass,radius,height,area,density=0.0;
6. boolean yesno=true;
7. Scanner scn = new Scanner(System.in);
8. System.out.println(“Enter mass of cylinder”);
9. mass=scn.nextDouble();
10. System.out.println(“Enter height of cylinder “);
11. height=scn.nextDouble();
12. System.out.println(“ Enter radius of cylinder<0 to test divide by zero and exit”);
13. radius=scn.nextDouble();
14. while(yesno){
15. try
16. { if( radius ==0.0) throw new ArithmeticException(“Divide By Zero”);
17. else
18. { area = 2*(22/7)*radius*(radius+height);
19. density=mass/area;
20. System.out.println(“
Density : “+ density);
21. System.out.println(“ Enter radius of cylinder<0 to test divide by zero”);
22. radius=scn.nextDouble();
23. }
24. }catch(ArithmeticException e)
25. {System.out.println(“
Divide By Zero Exception Occured”); yesno=false;}
26. }// end of while
27. }// end of main
28. }// end of DivideByZero
OUTPUT : Enter mass of cylinder 200
Enter height of cylinder 20
Enter radius of cylinder<0 to test divide by zero and exit 10
Density : 0.1111111111111111
Enter radius of cylinder<0 to test divide by zero and exit0
Divide By Zero Exception Occured
Exiting the program
Line Nos. 8 to 13: | obtains the data for finding out density of cylinder using the formula density = mass/area at Line No. 19 |
Line No. 15: | is a try block and Line No. 23 is a corresponding catch block that catches ArithmeticDivideByZero exception. We are simply informing the user and exiting the while loop and programme by making yesno=false. |
Line No. 16: | { if( radius ==0.0) throw new ArithmeticException (“Divide By Zero”); throw an exception when radius is zero. Thereafter catch block catches the exception. Note that we are using the parameterized constructor of ArithmeticException class. More importantly it is us who are throwing the exception by calling new new ArithmeticException() parameterized constructor. |
A try block can be made to initiate several exception objects. Accordingly catch blocks can catch multiple exception objects. The syntax and an example is shown in the next example.
Example 20.3: A Try block can Catch Multiple Exceptions Like IOexception, Index Out of Bouns Exception, etc. A Catch Block can Catch Multiple Exceptions Like IOexception , IndexOutOfBounds Exception, etc.
try
{ // allocation code here
public void DisplayNumbers() throws NumberFormatException{
//display code here that uses number formatting }
public int FindMaxArray( int a[] , int n) throws ArrayOutOfBoundsexception{
//FindMaxArray code here that uses Array processing
}
catch (NumberFormatException e1){ }
catch ( ArrayOutOfBoundsexception e2) { }
A try block can be nested just like for loop.
try // outer try
{ // allocation code here
try{ // inner try
// inner try block code here that uses File IO Statement}
public void HandleFile() throws FileNotFoundException{
// file handling code here that uses opening of file}
} catch (FileNotFoundException object) { }
}
catch (IOException object){ }
Usually when an exception occurs, the exception handling code may initiate retrun to system or calling program. At that instant of time, there are several actions to be performed like closing of all open files, restoring the state to a state prior to occurring of the exception, etc. This is accomplished by using the finally(), as shown in the next example. It is included after the last catch block.
Example 20.5: Using of Finally Block
try
{ // allocation code here
public void DisplayNumbers() throws NumberFormatException{
//display code here that uses number formatting }
public int FindMaxArray( int a[] , int n) throws ArrayOutOfBounds exception{
//FindMaxArray code here that uses Array processing
}
catch (NumberFormatException e1){ }
catch ( ArrayOutOfBoundsexception e2) { }
finally { // finally block
/* includes all house keeping code like saving current state ,closing of all open
objects and file and restoring the state to a state that existed prior to occurring of the
problem*/
} // end of finally block
A programmer can explicitly throw an exception. Throw can be for any of the exceptions provided by java.lang.Exception package or user-defined exception class. In the example that follows, we will show the user throwing an exception object for ArithmeticException class.
1. package com.oops.chap20;
2. import java.util.*;
3. public class MultiCatchFinally {
4. public static void main(String[] args){
5. double mass,area,density=0.0;
6. boolean yesno=true;
7. try{ // create arrays for mass ,area,density
8. double [] massArray = new double[]{200.00, 300.00,400.00,500.00};
9. double [] areaArray = new double []{ 20.0,30.0,40,0,0.0};
10. double [] densityArray = new double [massArray. length];
11. int len = massArray.length;
12. //for( int i=0; i<len+1;i++){
13. for( int i=0; i<len;i++){
14. if( areaArray[i]==0) throw new ArithmeticException(“Divide By Zero”);
15. else
16. densityArray[i]=massArray[i]/areaArray[i];}
17. System.out.println(“
mass area density”);
18. for( int i=0; i<len;i++){
19. System.out.println(“ ”+massArray[i]+” ”+areaArray[i]+” ”+densityArray[i]);}
20. }catch(ArithmeticException e)
21. {System.out.println(“Divide By Zero Exception has occurred ….”);}
22. catch(ArrayIndexOutOfBoundsException e)
23. {System.out.println(“Array out of Bounds Exception has occured ….”);}
24. finally{
25. System.out.println(“We are inside finally block & exiting the programme…….”);}
26. }// end of main
27. }//end of class
Run 1 We have commented out Line No. 12 to test array
//index out of bounds exception
OUTPUT1 :Divide By Zero Exception has occurred ….
We are inside finally block & exiting the programme…….
Run 2 We have commented out Line No. 13,14,and 15 to test Divide
//By Zero exception i.e ArithmeticException
OUTPUT2: Divide By Zero Exception has occured ….
We are inside finally block & exiting the programme…….
There is another variation called throws provided by java. We have been using this feature in all our IO related programs like public static void main(String [] args) throws IOException{. All checked exceptions, i.e., all checked exceptions are required to be handled by the user. However, if the user does not want to handle the exception, then he has to throw out using throws clause.
Example 20.7: MultiCatchFinally.java a Program to Show Multiple Catch Statements and Finally Block
package com.oops.chap20;
import java.io.*;
import com.oops.chap20.OurOwnException;
import java.lang.Exception;
import java.util.*;
class CheckCredits extends OurOwnException{
public void FindBal(String id,double trAmt) throws OurOwnException{
double[] BanBal=new double[]{2000.0,5000.00,900.00,90000.0};
String[] EmpIdNo=new String[]{ “50595”,”50596”,”50597”,”50598”};
for(int i=0;i<EmpIdNo.length;i++){
if( EmpIdNo[i].compareTo(id)==0)
{ System.out.println(“Bank balance” +BanBal[i]);System.out.
println(“Trnsaction Amount “ +trAmt );
if ( BanBal[i]- trAmt <1000.00)
throw new OurOwnException(“Sorry Transaction can not be
processed Bal<1000.00”);
else System.out.println(“Successful”); }
else continue;
}// end of for
}// end of FindBal
}// end of CheckCredits class
class MyException {
public static void main(String[] args)throws IOException{
String idNo, amt; boolean yesno=true;
double transAmt;// variables for input data
BufferedReader input = new BufferedReader (new InputStreamReader (System.in));
System.out.println(“Enter id number of Employee”);
String stg = input.readLine();stg.trim();
System.out.print(“Enter Transaction amount :”);
amt=input.readLine();amt.trim();
transAmt=Double.parseDouble(amt);
// make an object of CheckCredits class
CheckCredits obj=new CheckCredits();
// call FindBal
try{
obj.FindBal(stg,transAmt);
}catch(OurOwnException e){
System.out.println(“Inside catch block - Our Own Exception”);
System.out.println(e.getMessage());}
}// end of main
}// end of class MyException
OUTPUT : Enter id number of Employee 50596
Enter Transaction amount :25000.00
Bank balance5000.0 Trnsaction Amount 25000.0
Inside catch block - Our Own Exception
Sorry Transaction cannot be processed Bal<1000.00
Suppose an exception occurs at some method but the corrective mechanism is placed at some other method, say main()method, then the exception caught by catch block of called method can re thrown, so that main() will catch the re-thrown exception and carry out the correcting mechanism. Example 1 and 2 show how to catch re-thrown exceptions for String and Array.
On many occasions, we need to define our own exception handlers in project development work like exception during data validations, data validations, etc. We need to throw exception object and then write a catch block to capture this exception. Exception class is super for all exceptions that occur. The class hierarchy for Exception classes is shown in Figure 20.1.
1. package com.oops.chap20;
2. import java.lang.Exception;
3. class OurOwnException extends Exception{
4. OurOwnException(){} // default constructor
5. OurOwnException(String stg){super(stg);} // constructor with arg
6. }// end of own exception
7. class OwnException1{
8. public static void main(String[] args) {
9. double credits = 20000.00;
10. double debits = 19900.00;
11. try{
12. if ( ( credits-debits)<1000.00 )
13. throw new OurOwnException(“Sorry Transaction can not be processed. Bal is <1000.00”);
14. else
15. System.out.println(“Transaction sucessful”);
16. }catch(OurOwnException e)
17. {System.out.println(“Inside a catch block- OurOwnException”);
18. System.out.println(e.getMessage());}
19. }//end of main
20. }// end of ownException1
OUTPUT : Inside a catch block- OurOwnException
Sorry Transaction can not be processed. Bal is <1000.00
Line No. 3: | class OurOwnException extends Exception{ shows OurOwn exception class extending to java.lang.Exception class. |
You are familiar with picture in picture facility provided by television wherein while the newsreader is presenting the news, a small window appears with a totally different news item or amplification of what the newsreader is presenting, probably cricketing action. How is this possible? Surely you need two independent executions.
What is a thread? Simply put, thread to Java is the same as process to an operating system. Thread is a sequence of instructions that will be executed when the CPU is scheduled to handle the thread. The void main() programs so far we have been executing were indeed executed by Java on a single thread. This concept is shown in Figure 20.3.
Figure 20.3 Multithreaded program
When more than one thread is executing independent processes, it is called a multithreaded program. Why is multithreaded programming required? Multithreading is useful in any situation where a programmer requires more than one task to be handled at the same time. Situations like games programming, foreground and background jobs, concurrent handling of multiple outputs, etc., are ideally suited for multithreaded programming. Threaded and multithreaded programs are ideally suited for client server programs wherein the server handles clients residing on several threads.
A process is a job in hand. We can also say that this is a simple sequence of instructions to be executed by the CPU. Operating system creates several processes. CPU is then scheduled to handle different processes based on the priorities of the processes by OS. OS switches CPU amongst processes and allocates CPU time and completes all the tasks. When process shifting takes place, it is necessary to save the context of the current execution like stack, variables, status, etc. As context switching is involved, processes are called heavyweight processes.
Java brings concurrent processing, not parallel, just like OS does with its processes, within the preview of programmers by innovative and unique feature called multithreaded programming. In multithreaded programs, the main program is run on a main thread but the main program creates threads that run independent and concurrent program flows. It is the main program that creates and starts the other three threads, as shown in Figure 20.3. Once started, the three subthreads run independently as per priorities set and as per scheduling of CPU concurrently sharing CPU time and other common resources.
Threads are also called light weight because they consume less memory resources. Why because there is no context switching involved in multithreaded programming.
By default, our main program is running on the main thread. To create our own threads, the following steps are used:
Step 1: A thread can be created either by extending to Thread class or implementing the Runnable Interface.
Example: class ThreadTest extends Thread or
Class ThreadTest implements Runnable
class ThreadTest extends Thread{ or
class ThreadTest extends implements Runnable{
public void run()
{……………..}
Note that run method is where the entire action for the thread will take place. It is like the main() method. It can declare its own variables, instantiate other classes. Run is the entry point for any new thread that is created. The Thread created ends when the run() ends.
class ThreadTestDemo{
public static void main( String[] args) {
ThreadTest obj =new ThreadTest();
Thread thrd = new Thread(obj); OR
Thread thrd = new Thread( obj , “threadname”);
Thrd.start();
We can suspend the thread from execution for a specified period of time by using sleep() method. The syntax is: static void sleep(milliseconds) throws InterruptedException or static void sleep (milliseconds, nanoseconds) throws InterruptedException. As sleep is a static method, we can invoke directly as: Thread.sleep(ms); During the time thread is suspended, CPU is allocated to other threads.
Thread class also provides getName() and setName() methods, for example, Thread.getname() and Thread.setName(“name”). The methods by Thread class and Runnable interface are shown in Table 20.2.
Table 20.2 Methods of thread class and runnable interface
Method | Remarks |
---|---|
getName(); setName(stg); |
Obtain and set names for the threads |
getPriority() setPriority() |
Get & set methods to obtain and set Priorities |
isAlive() join() |
To check if thread is still running It throws InterruptedException. Calling thread waits till specified thread joins it. |
sleep(ms) sleep(msec,nsec) |
Suspend execution of thread for ms duration Suspend execution of thread for ms & nano sec duration |
We implement the creation of threads using extends method in Example 20.8. We show the implementation using Runnable interface in Ex 20.4. Runnable is an interface provided to create the threads. The programmer has to execute overridden run() to create and run the thread.
Example 20.9: FirstThreademo.java A Program to Show How to Create and Run Thread. Use Extends Feature to Create Threads
1. package com.oops.chap20;
2. class FirstThread extends Thread{
3. public void run(){
4. // Thread executes the sequence
5. try{
6. for (int i=0;i<4;i++)
7. {System.out.println(“ thread1 :” + i + “ : “);
8. Thread.sleep(600);
9. }
10.} catch(InterruptedException e )
11. {System.out.println(“thread1 interrupted”);}
12. System.out.println(“Exiting from thread1”);
13. }//end of run
14. }//end of FirstThread
15. class SecondThread extends Thread{
16. public void run(){
17. try{
18. for (int i=0;i<4;i++)
19. { System.out.println(“ thread2 :” + i + “ : “);
20. Thread.sleep(600);
21. }
22. }catch(InterruptedException e )
23. {System.out.println(“thread2 interrupted”);}
24. System.out.println(“Exiting from thread2”);
25. }//end of run
26. }//end of SecondThread
27. public class FirstThreadDemo {
28. public static void main(String[] args) {
29. //create an object of FirstThread & SecondThread
30. FirstThread obj1 = new FirstThread();
31. SecondThread obj2 = new SecondThread();
32. //create the Thread and attach it to object
33. Thread thread1 = new Thread( obj1);
34. Thread thread2 = new Thread( obj2);
35. //Run the thread by calling start() which calls run()
36. thread1.start();
37. thread2.start();
38. try{
39. for (int i=0;i<4;i++)
40. { System.out.println(“ threadMain :” + i + “ : “);
41. Thread.sleep(1200);
42. }
43. }catch(InterruptedException e )
44. {System.out.println(“main thread interrupted”);}
45. System.out.println(“Exiting from main thread”);
46. }//end of main
47. }//end of FirstThreadDemo
Output: threadMain :0 :
thread1 :0 : thread2 :0 : thread2 :1 : thread1 :1 : threadMain :1
thread2 :2 : thread1 :2 : thread1 :3 : thread2 :3 : th readMain :2
Exiting from thread1 Exiting from thread2 threadMain :3 :
Exiting from main thread
Line Nos. 30 & 31: | instantiate FirstThread and SecondThread. These threads extend to Thread class. |
Line Nos. 33 & 34: | create the Thread objects and attach them with objects: Thread thread1 = new Thread( obj1); |
Line Nos. 36 & 37: | starts the thread which in turn call the run()method. Both thread1 and thread2 start running. |
Line Nos. 38–45: | describe main thread. Note that at line no: 41 sleep(1200) ensures that main thread sleeps for 1200 seconds. During this time other threads are handled by CPU. |
Line No. 6: | FirstThread in side run() methods executes a for loop as part of its programme. After each loop, the thread goes to sleep for 600 ms to facilitate SecondThread and MainThread to get their share of CPU. |
Line Nos. 15–26: | declare a class SecondThread identical to FirstThread. |
Note that both threads wait only for 600 ms and main thread waits for 1200ms . his timings are deliberately chosen to ensure that main thread finishes last.
Use Inheritance extends Thread method if you have anything new to add in subclass. Else implementing Runnable is a better option. In our next example, we will introduce constructors to create threads. We will use Runnable interface:
Example 20.10: SecondThreadDemo.java A Program to Show How to Create and Run Thread. Use Extends Feature to Create Threads
1. package com.oops.chap20;
2. class FirstThread2 implements Runnable{
3. Thread thrd1;
4. FirstThread2(){
5. System.out.println(“Creating FirstThread2”);
6. thrd1 = new Thread(this,”FirstThread2”);
7. System.out.println(“Creating FirstThread2”+ thrd1);
8. thrd1.start();
9. }
10. public void run(){
11. // FirstThread2 executes the sequence
12. try{
13. for (int i=0;i<4;i++)
14. {System.out.println(“ thread1 :” + i + “ : “);
15. Thread.sleep(600);}
16. }catch(InterruptedException e )
17. {System.out.println(“thread1 interrupted”);}
18. System.out.println(“Exiting from thread1”);
19. }//end of run
20. }//end of FirstThread
21. class SecondThread2 implements Runnable{
22. Thread thrd2;
23. SecondThread2(){
24. System.out.println(“Creating SecondThread2”);
25. thrd2 = new Thread(this,”FirstThread2”);
26. System.out.println(“Creating SecondThread2”+ thrd2);
27. thrd2.start();
28. }
29. public void run(){
30. System.out.println(“thread1 Details”);
31. System.out.println(“Name :”+thrd2.getName());
32. System.out.println(“Priority :”+thrd2.getPriority());
33. try{
34. for (int i=0;i<4;i++)
35. { System.out.println(“ thread2 :” + i + “ : “);
36. Thread.sleep(600);
37. }
38. }catch(InterruptedException e )
39. {System.out.println(“thread2 interrupted”);}
40. System.out.println(“Exiting from thread2”);
41. }//end of run
42. }//end of SecondThread
43. public class ThreadsConstDemo {
44. public static void main(String[] args) {
45. //create an object of FirstThread2 & SecondThread2
46. new FirstThread2();
47. new SecondThread2();
48. try{
49. for (int i=0;i<4;i++)
50. { System.out.println(“ threadMain :” + i + “ : “);
51. Thread.sleep(1200);
52. }
53. }catch(InterruptedException e )
54. {System.out.println(“main thread interrupted”);}
55. System.out.println(“Exiting from main thread”);
56. }//end of main
57. }// end of ThreadRunnableDemo
Output: Creating FirstThread2
Creating FirstThread2Thread[FirstThread2,5,main]
thread1 :0 :
Creating SecondThread2
Creating SecondThread2Thread[FirstThread2,5,main]
threadMain :0 :
thread1 Details
Name :FirstThread2
Priority :5
thread2 :0 : thread1 :1 : thread2 :1 : thread1 :2 :
threadMain :1 : thread2 :2 : thread1 :3 : thread2 :3 :
Exiting from thread1 threadMain :2 : Exiting from thread2
threadMain :3 : Exiting from main thread
Line Nos. 46 & 47: | creates new thread by : new FirstThread2();new Second Thread2(); |
Line No. 6: | thrd1 = new Thread(this,”FirstThread2”); attaches new thread created with this ( current thread) and names it as FirstThread2 |
Line No. 8: | starts the thread1. Yhread enter run() method. |
Line Nos. 30–32: | gets you thread details |
System.out.println(“thread1 Details”);
System.out.println(“Name :”+thrd2.getName()); System.out.println (“Priority :”+thrd2.getPriority());
The sleep() method introduced suspends a thread for duration specified and CPU is shifted to other waiting threads. The selection of duration is arbitrary and CPU is forcibly pulled out from thread after time duration. This is not a satisfactory solution. Java provides: final boolean isAlive() method to test if the thread is alive. Java also provides a more elegant method called final void join() throws InterruptedException. This is a non-greedy method and it waits till the thread on which it is called is terminated. Here the calling thread waits till the specified thread joins it.
Example 20.11: IsAliveJoinDemo.java A Program to Show How to Create and Run Thread. Use Extends Feature to Create Threads
1. package com.oops.chap20;
2. import com.oops.chap20.FirstThread2;
3. import1 com.oops.chap20.SecondThread2;
4. public class IsAliveJoinDemo {
5. public static void main(String[] args) {
6. FirstThread2 obj1= new FirstThread2();
7. SecondThread2 obj2 =new SecondThread2();
8. // check if threads are alive. thrd1&2 is objects of First/SecondThread2
9. System.out.println(obj1.thrd1.isAlive()); //thrd1 is object of FirstThread2
10. System.out.println(obj2.thrd2.isAlive());
11. // wait for threads to finish. Use join method
12. try{
13. System.out.println(“
waiting for threads to finish”);
14. obj1.thrd1.join();
15. obj2.thrd2.join();
16. }catch(InterruptedException e )
17. {System.out.println(“main thread interrupted”);}
18. System.out.println(“Exiting from main thread”);
19. }//end of main
20. }// end of ThreadRunnableDemo
Output: Creating FirstThread2
Creating FirstThread2Thread[FirstThread2,5,main]
thread1 :0 : Creating SecondThread2
Creating SecondThread2Thread[FirstThread2,5,main]
True true
thread1 Details waiting for threads to finish
Name :FirstThread2 Priority :5
thread2 :0 : thread1 :1 : thread2 :1 : thread1 :2 : thread2 :2 :
thread1 :3 : thread2 :3 : Exiting from thread1Exiting from thread2
Exiting from main thread
There are five states for thread to be in. They are: NewBorn), Runnable, Running, Blocked, and Dead State. A running thread can be stopped by stop() method. A thread can be blocked by any one of the following methods:
A newborn thread goes to either Runnable state or Dead State. With start() method the thread goes to Runnable state. Runnable state means that the thread is ready and waiting in the queue to be serviced by CPU. Depending on the priority or on the basis of round robin the threads are scheduled to be serviced by CPU. The thread then goes to the running state.
Now sleep() or suspended() or wait() takes the thread to a blocked state. Blocked state is one which will not be handled by a CPU. Resume or notify() or notifyall() will take the thread to runnable state. Notify() and notifyall() are methods invoked by thread that has completed its job with CPU and issues notify() or notifyall(). Depending on the priority, the thread with the highest priority gets CPU's attention.
Figure 20.4 The states that a newborn thread goes through
Thread priority decides the order of scheduling of thread waiting. Thread priority is from No. 1 to 10. We can set the priority with:
ThreadName.setPriority(int ); or ThreadName.setPriority(NORM _PRIORITY );
Int can be any number between 1 and 10.
MIN_PRIORITY =1 : NORM _PRIORITY =5 MAX _PRIORITY =10
Java executes the highest priority thread first. The lower priority thread gets CPU attention when higher priority thread is stopped or sleep() is used or wait() is executed. When a thread is running if higher priority thread arrives, it preempts the running thread and schedules the higher priority thread. The running thread goes to Runnable state.
Example 20.12: Priority.java: A program to Show How to Set Priorities to the Threads
1. package com.oops.chap20;
2. class MaxPriority implements Runnable{
3. Thread thrd1;
4. MaxPriority(){
5. System.out.println(“Creating MaxPriority”);
6. thrd1 = new Thread(this,”MaxPriority”);
7. thrd1.setPriority(Thread.MAX_PRIORITY);
8. System.out.println(“Creating MaxPriority”+ thrd1);
9. thrd1.start();
10. }
11. public void run(){
12. System.out.println(“Maximum Thread Details”);
13. System.out.println(“Name :”+thrd1.getName());
14. System.out.println(“Priority :”+thrd1.getPriority());
15. // MaxPriority executes the sequence
16. try{
17. for (int i=0;i<4;i++)
18. {System.out.println(“ thread1 :” + i + “ : “);
19. Thread.sleep(600);}
20. }catch(InterruptedException e )
21. {System.out.println(“thread1 interrupted”);}
22. System.out.println(“Exiting from thread1”);
23. }//end of run
24. }//end of FirstThread
25. class MinPriority implements Runnable{
26. Thread thrd2;
27. MinPriority(){
28. System.out.println(“Creating MinPriority”);
29. thrd2 = new Threadthis,”FirstThread2”);
30. thrd2.setPriority(Thread.MIN_PRIORITY+2);
31. System.out.println(“Creating MinPriority”+ thrd2);
32. thrd2.start();
33. }
34. public void run(){
35. System.out.println(“minimum thread Details”);
36. System.out.println(“Name :”+thrd2.getName());
37. System.out.println(“Priority :”+thrd2.getPriority());
38. try{
39. for (int i=0;i<4;i++)
40. { System.out.println(“ thread2 :” + i + “ : “);
41. Thread.sleep(600);
42. }
43. }catch(InterruptedException e )
44. {System.out.println(“thread2 interrupted”);}
45. System.out.println(“Exiting from thread2”);
46. }//end of run
47. }//end of SecondThread
48. public class Priority {
49. public static void main(String[] args) {
50. //create an object ofMaxPriority & MinPriority
51. new MaxPriority();
52. new MinPriority();
53. try{
54. for (int i=0;i<4;i++)
55. { System.out.println(“ threadMain :” + i + “ : “);
56. Thread.sleep(600);
57. }
58. }catch(InterruptedException e )
59. {System.out.println(“main thread interrupted”);}
60. System.out.println(“Exiting from main thread”);
61. }//end of main
62. }// end of Priority.java
Output: Creating MaxPriority
Creating MaxPriorityThread[MaxPriority,10,main]
Maximum Thread Details
Name :MaxPriority
Priority :10
thread1 :0 :
Creating MinPriority
Creating MinPriorityThread[FirstThread2,3,main]
threadMain :0 :
minimum thread Details
Name :FirstThread2 Priority :3
thread2 :0 : thread1 :1 : thread2 :1 : thread1 :2 : threadMain :1 : thread2 :2 : thread1 :3 : thread2 :3 : Exiting from th read1
threadMain :2 : Exiting from thread2 threadMain :3 :
Exiting from main thread
Line Nos. 51 & 52: | create two threads called MacPriority and MinPriority. |
Line No. 7: | Constructor allocates priority as MAX_PRIORITY i.e. 10 to thrd1 |
Line No. 30: | Constructor allocates priority as MIN_PRIORITY+2, i.e., 3 to thread 2 |
Line Nos. 12 to 14: | provide the details of thread1 such as name, priority, etc. |
As per priorities set, if you observe the output thread1 with priority of 10 is completed First. The main thread by default has NORM _PRIORITY =5 which is higher than Thread2 priority which is MIN_PRIORIT +2, i.e., 3. Hence the main thread completes before thread2.
When multiple threads act on different objects, we would call it multitasking. As per priorities allocated and as per CPU scheduling, the threads execute different objects and produce results. There is no problem in this case.
Suppose multiple threads act on the same object. This could lead to problems. Let us say that there are two threads, thread1 & thread2, acting on the object, i.e., they will concurrently execute the same run() command. Each thread has only one job, that of incrementing the counter and sending it to the printer for printing. The output we are expecting is: thread1 1001,thread2: 1001; thread:1002, thread2: 1002 and so on. Remember thread is on CPU and speed of execution is of the order of nanoseconds and the printer is a slow device. Let us say that counter has an initial value of 1000. After incrementing by thread1 to 1001 and before the count has been printed, i.e., 1001, the control may pass to thread2 due to sleep() or wait(), etc., which will increment the counter to 1002. The printer will look for count and print 1002 instead of 1001 which we normally expect, thus leading to erroneous results. A second scenario is that after printing 1001, if the CPU is still with thread1, it will increment once again and print 1002, thus leading again to erroneous results. Multiple threads working independently on a single object and plausible problems that can arise are shown in Ex 20.6.
Figure 20.5 Multiple objects on a single object
Java has provided a feature called synchronization that helps us to solve the problems of multiple threads sharing common resources and using the same object like printer. For example, we could use: synchronized void UpDateCount(){ // code to be synchronized here….}
Java creates a monitor for the UpDateCount() and hands its over to thread that has entered the object. It is like a key. The other objects join a queue waiting for their turn to enter the Member method UpDateCount(). Thus there is no conflict. But what is the price of synchronization? Simply the process has become serial handling of the thread rather than concurrent handling. It is similar to Railway trains waiting at the platform to cross a bridge that has only one track. A second train cannot enter the bridge section until and unless the train completes the bridge section and notifies signal) it to that effect. operations.
Example 20.13: SynchronisedDemo.java: A Program to Show Use of Synchronized Block for Solving Problems of Multiple Threads Acting on Single Object
1. package com.oops.chap20;
2. class Sync3 extends Thread{
3. Thread thrd;
4. Sync3(String stg){
5. super(stg);}
6. public void run(){
7. synchronized(this) {
8. try{
9. for(int i=1000;i<1010;i++)
10. {System.out.println(this.getName() + (i) + “ : “);
11. Thread.sleep(500);
12. }
13. }catch(InterruptedException e )
14. {System.out.println(“thread1 interrupted”);}
15. System.out.println(“Exiting from thread1”+this.getName());
16. }//end of try
17. }//end of run
18. }
19. public class SynchronisedDemo {
20. public static void main(String[] args) {
21. //create an object ofMaxPriority & MinPriority
22. Sync3 obj1 =new Sync3(“Sync1”);obj1.start();
23. Sync3 obj2 = new Sync3(“Sync2”);obj2.start();
24. }//end of main
25. }// end of class SynchronisedDemo
Sync11000 : Sync20000 : Sync11001 : Sync20001 : Sync11002 :
Sync20002 : Sync11003 : Sync20003 : Sync11004 : Sync20004 :
Sync11005 : Sync20005 : Sync11006 : Sync20006 : Sync11007 :
Sync20007 : Sync11008 : Sync20008 : Sync11009 : Sync20009 : Exiting from thread1Sync1 Exiting from thread1Sync2
Line No. 7: | Declares the block as synchronized(this) meaning it is synchronizing the object so that object holds the monitor and till it relinquishes the CPU other threads can not enter this block of code. |
Threads need to communicate with one another either to pass arguments, synchronize and optimize the performance. There is definitely a speed mismatch between producer and consumer.
Consider for example the action of inputting data from the keyboard into the computer. The steps involved in this process include:
Example 20.14: ProducerConsumer.java: A Program to Show the Inter-thread Communications
1. package com.oops.chap20;
2. class Producer extends Thread{
3. // producer produces data and add it to buffer based on the signal
4. StringBuffer buffer;
5. Producer(){ // constructor
6. buffer = new StringBuffer();}
7. public void run(){
8. // synchronize the buffer
9. synchronized(buffer)
10. {
11. //produce items
12. for( int i=1;i<=8;i++)
13. { try {
14. buffer.append(“Item”+i + “,”);
15. Thread.sleep(200);
16. System.out.println(“Buffer Position :”+ i + “ Filled.”);
17. }catch(Exception e){}
18. }//end of for
19. buffer.notify();
20. }// end of synchronized block
21. }//// end of run
22. }// end of Producer
23. class Consumer extends Thread{
24. // Create a reference of Producer class
25. Producer prod;
26. //Constructor
27. Consumer(Producer prod)
28. { this.prod=prod;}
29. public void run(){
30. synchronized(prod.buffer)
31. {// wait for notification from Producer
32. try{
33. prod.buffer.wait();
34. }catch(Exception e){}
35. System.out.println(“Displaying items from Buffer..”);
36. System.out.println(prod.buffer);
37. }//end of sync
38. }// end of run
39. }//end of class Consumer
40. public class ProducerConsumerDemo extends Thread{
41. public static void main(String[] args) throws Exception {
42. // create objects of producer and consumer
43. Producer prod = new Producer();
44. Consumer cons = new Consumer(prod);
45. // create threads for Producer and Consumer
46. Thread thrdProd = new Thread(prod);
47. Thread thrdCons = new Thread(cons);
48. thrdCons.start();
49. thrdProd.start();
50. }// end of main()
51. }// end of class ProducerConsumerDemo
Output:
Buffer Position :1 Filled. Buffer Position :2 Filled.
Buffer Position :3 Filled. Buffer Position :4 Filled.
Buffer Position :5 Filled. Buffer Position :6 Filled.
Buffer Position :7 Filled. Buffer Position :8 Filled.
Displaying items from Buffer.
Item1,Item2,Item3,Item4,Item5,Item6,Item7,Item8
Line Nos. 43 & 44: | create objects for Producer and Consumer. |
Line Nos. 46 & 47: | create new thread objects thrdProd and thrdCons. |
Line Nos. 48 & 49: | start the threads. |
Line No. 4: | creates StringBuffer object called buffer and constructor at Line No. 6 allocates resources. |
Figure 20.6 Producer consumer problem
Producer produces in a for loop continuously and fills up the buffer through append statement at Line No. 14. Note that buffer is in a synchronized block defined at Line No. 9.
Producer notify(0 at Line No. 19 to the threads waiting on the object.
Consumer creates an instance of Producer at Line No. 25 and constructor receives the reference to Producer as argument and allocates resource at Line Nos. 27 and 28.
Line No. 30: | block is synchronized with object of Producer buffer . |
Line No. 33: | consumer thread is waiting for notify(0 from the producer at Line No. 19. This is achieved by wait() command at Line No. 33 : prod.buffer.wait(); |
A deadlock will occur if there are two synchronized objects and if two threads working independently on these synchronized objects have circular dependency. Suppose there are two synchronized objects, i.e., each object has a monitor. Let the objects be Obj1 and Obj2. Let there be two threads, thread1 and thread2, created which enter the respective monitors on Obj1 and Obj2. Now Obj1 calls any synchronized method on Obj2, the thread1 will be blocked because thread2 has the monitor. So far so good.
Now what happens if thread2 calls a method on Obj1? Surely it will be blocked because thread1 has the monitor on obj1.
Thus, we can see a circular dependency on a pair of synchronized objects. A deadlock occurs. For a deadlock to occur, the following conditions are a must:
A deadlock cannot be prevented but its occurrence can be minimized. When a deadlock occurs, the threads are immediately stopped, resources are released and processes are restarted.
TRUE/FALSE
TRUE/FALSE
TRUE/FALSE
18.224.30.19