Exception Handling & Multithreading Exception: An exception is an abnormal condition that interrupts the flow of execution and the control comes out of the program abruptly. Such an abnormal condition may at times corrupt some private or confidential files or may make the data inconsistent. So when an exception occurs, we have to see that the controls comes out of the program smoothly without corrupting any data, or leaving the objects in inconsistent state. And java provides the exception handling techiniques to deal with the exceptions.
Types of Exceptions: Exceptions can be classified into2 types. Exception classes hierarchy: Throwable(class) Error RuntimeException ArithmeticException ArrayIndexOutOfBoundsException NumberFormatExcption NullPointerException StringIndexOutOfBoundsException ClassCastException IllegalStateException SecurityException NegativeArraySizeException
Exception IOExceptions ClassNotFoundException NoSuchFieldException NoSuchMethodException InterruptedException IllegalAccessException CloneNotSupportedException IllegalAccessException
The Throwable class is the super class of all the exception classes and exists in java.lang package. As java.lang package is the default package available to all the classes, all these exception classes can be directly used in the programs. ArithmeticException – This exception occurs by a divide by zero operation. ArrayIndexOutOfBoundsException- Occurs if accessing an array value with the out of bounds index is accessed. NumberFormatException- Occurs when converting a string to numeric format. NullPointerException – Occurs on using a null reference. ClassCastException – Occurs when trying cast incompatible type class. StringIndexOutOfBoundsException - Occurs if operating string with the out of bounds index.
InterruptedException – When one thread interrupts another thread. ClassNotFoundException- Class not found. NoSuchMethodException – When a requested method is not found. NoSuchFieldException- When a requested field is not found.
Exception Handling: The process of dealing with the abnormal conditions of trying to handle the caused exception is called exception handling. In java exceptions are objects. There is a predefined class called Exception in java.lang package. Ex: Line 1 class ExceptionDemo{ 2 public static void main(String[] args){ 3 System.out.println(“Dividing 5 by 0”); 4 int a = 5/0; 5 System.out.println(“A = “+ a); 6 } 7 } The division of any value by zero is not defined in java, so this line will throw the Divide by zero exception. At line no. 4, an ArithmeticException class object is created and thrown out of the main method, and the execution stops. So the line no. 5 doesn’t print the given string to the console.
Using try, catch & finally blocks: The The corresponding catch block will catch the exception thrown by the try block and will handle it. Finally block is that block that is executed either of the conditions, exception raised or not raised. Ex: class ExceptionDemo{ public static void main(String[] args){ int a= 10; System.out.println(“Start”); try{ while(true){ int b = 100/a; System.out.println(“A = “+ a+ “ B= “+b); a-=2; } }catch(ArithmeticException ae){ System.out.println(“Exception handled :+ ”ae.getMessage());
} finally{ System.out.println(“End”); } } } An ArithmeticException object is thrown out of try block, which is caught by the respective catch block. A try block must be followed by atleast one catch or finally blocks. A try block can be followed by more than one catch block. Multiple catch blocks: Ex: class MultipleCatchBlocksDemo{ public static void main(String[] args){ int a= 10; System.out.println(“Start”); try{ String s= null; int length = s.length(); int a = 5/ 0; int b=’c’; }catch(ArithmeticException ae){ System.out.println(“Arithmetic Exception: ”+ae.getMessage()); }catch(NullPointerException np){ System.out.println(“ NullPointerExceptionException:” +ae.getMessage()); }catch(NumberFormatException nf){ System.out.println(“Number format Exception:”+ ae.getMessage()); } finally{ System.out.println(“End”); } } } The code in the try block can raise Arithmetic Exception, Null pointer exception of the number format exception.
In this case only one of the catch blocks will get executed. This depends on the exception that is thrown first of the try block. So as per the code, NullPointerException object is thrown from the try block. If there is no matching catch block then the exception is handled by the java runtime environment which is the JVM. Instead of giving it to runtime environment, we can place a catch block of type catch(Exception e){ …} . Will handle any kind of exception as Exception is the super class of all other types of exceptions.
The throws keyword: Instead of using the try catch blocks, we can use the throws keyword with the method signature to postpone the exception handling by passing it to the calling method. A throws clause lists he type of exceptions that a method might throw. Ex: class ThrowsDemo{ public static void methodA() throws ArithmeticException, NullPointerException, NumberFrmatException { String s= null; int length = s.length(); int a = 5/ 0; int b=’c’; } public static void main(String[] args){ int a= 10; System.out.println(“Start”); try{ methodA(); }catch(ArithmeticException ae){ System.out.println(“Arithmetic Exception: ”+ae.getMessage()); }catch(NullPointerException np){ System.out.println(“ NullPointerExceptionException:” +ae.getMessage()); }catch(NumberFormatException nf){ System.out.println(“Number format Exception:”+ ae.getMessage()); } System.out.println(“End”); }
Here the main() method is calling the methodA() which raises some exceptions. It is declaring using the throws keyword that it the 3 exceptions, so the control goes from methodA() to its calling methid main (), where the exception is handled.
The throw keyword:Exceptions are thrown using the throw keyword. When ever an exception is raised, the respective exception object is created and thrown using thow. Ex: try{ ArithmeticException ae = new ArithmeticException() ;’ throw ae; }catch(Exception e){..}
Built-in Exceptions: Java defines built-in Exception classes in java.lang package. The java.lang package is the package by default available to all classes. The super class of all exceptions class is the Exception class.Every other exception is the subclass of this class. These are classified as checked exceptions and unchecked exceptions. A checked exception is any subclass of Exception (or Exception itself), excluding class RuntimeException and its subclasses The compiler forces the programmers to specify the list of exceptions that might be thrown by the corresponding methods. Unchecked exceptions are RuntimeException and any of its subclasses. Class Error and its subclasses also are unchecked. The unchecked exception are not checked for declaration by compiler.
Creating own Exception subclasses : We can create our own custom exceptions. Throwable is the super class of all the exception subclases. To create an Exception of our own type class MyException extends Exception{ ….. } Since MyException class extends an Exception , it is also an exception. Ex: class AgeException extends Exception{ int age; public AgeException(int age){ this.age = age; } public String toString(){
System.out.println(“Age Exception as “+ age+ is not the valid age to apply for the given post”); } } Now We have created a new Exception called AgeException. Using the created AgeException class: class ApplicationDemo{ public void validateAge(int age){ if(age<=21 || age>=30){ throw new AgeException(age); } } public static void main(String[] args){ ApplicationDemo ad = new ApplicationDemo(); try{ ad.validateAge(30); }catch(AgeException ae){ System.out.println(“Exception caught: “+ae); } } }
Multithreading : Definition of a thread: A thread is a single sequential flow of control within a program. Multithreading: The process of executing multiple such threads with separate flow of controls simultaneously is called multithreading. A process is a program that is currently in execution. A thread is a subtask in a program. So a process is a program that is executing using single or multiple threads.
Difference between a thread and a process: Process 1) A process is a program that is currently in execution. 2) Processes are heavy weight tasks that require their own separate address space 3) Inter process communication is expensive and limited.
Thread 1) A thread is a single sequential flow of control within a program 2) A thread is a light weight and shares the same address space. 3) The inter thread communication is inexpensive and context switching from thread to another is low cost.
Thread life cycle:
Start run()
sleep(), wait()
Run notify(), notifyAll()
Wait
Dea d
Creating a thread: Threads are also objects in java. There is a Thread class defined in java.lang package. To create threads in java 1) create objects of this class or 2) create a class make it a subclass of Thread class or 3) Create a class and implement Runnable interface. Creating a thread using Thread class:Ex: class MyThread extends Thread{ String threadName; public MyThread(String name){ threadName = name; start(); } public void run(){ for(int i = 0; i< 5 ; i++) System.out.println(threadName +“ = “+i); } } class ThreadDemo{ public static void main(String args[]){ MyThread thread1 = new MyThread(“Thread1); MyThread thread2 = new MyThread(“Thread2); MyThread thread3 = new MyThread(“Thread3); } } Creating a thread using Runnable Interface:-
class MyThread implements Runnable{ String threadName; public MyThread(String name){ threadName = name; start(); } public void run(){ for(int i = 0; i< 5 ; i++) System.out.println(threadName +“ = “+i); } } class RunnableDemo{ public static void main(String args[]){ MyThread myThread1 = new MyThread(“Thread1”); Thread t1 = new Thread(myThread1); MyThread myThread2 = new MyThread(“Thread2); Thread t2 = new Thread(myThread2); MyThread myThread3 = new MyThread(“Thread3); Thread t3 = new Thread(myThread3); } }
Thread Priorities: From an abstract or a logical perspective, multiple threads execute as concurrent sequences of instructions. In single CPU cases threads will not execute in parallel at the same time. In java we can the prioritize the threads execution. This can be done by the api’s defined in the Thread class. Methods: final void setPriority(int priority) : Sets the given priority to the thread final int getPriority() : Returns the thread priority. Priority is an integer value between 1 and 10. 1 is the minimum priority and 10 is the maximum priority. Priority values as defined as constants in Thread class as public static final int MIN_PRIORITY =1;
public static final int NORM_PRIORITY =5; public static final int MAX_PRIORITY =10; Ex: MyThread thread1 = new MyThread(“Thread1); MyThread thread2 = new MyThread(“Thread2); MyThread thread3 = new MyThread(“Thread3); thread1.setPriority(1); thread2.setPriority(9); thread3.setPriority(4); or thread1.setPriority(Thread.NORM_PRIORITY); The higher priority threads get allocation of the maximum CPU time, where the low priority threads get the allocation of minimum CPU time.
Synchronization: When two or more threads are trying to access the same shared resource, then there should be some kind of coordination, which takes care of the allocating the shared resource to single thread at a time. This process is called synchronization. It is the concept called monitor. A monitor is an object that is used as a mutually exclusive lock called mutex. When a thread enters the monitor it acquires the monitor, and no other thread can enter the monitor, until the first thread exits the monitor. The other threads will be in the waiting state. In java, synchronization is achieved through synchronized keyword or the synchronized blocks. If we use the synchronized keyword with a method declaration, the method cannot be access by multiple threads at the same time. public synchronized void sharedMethod(); Ex: class ThreadSynchronization{ public static void main(String[] args){ MyThread thread1 = new MyThread(“Thread1 : “);
MyThread thread2 = new MyThread(“Thread2 : “); thread1.start(); thread2.start(); boolean thread1IsAlive = true; boolean thread2IsAlive = true; do{ if(thread1IsAlive && thread1.isAlive()){ thread1IsAlive = false; System.out.println(“Thread1 : dead); } if(thread2IsAlive && thread2.isAlive()){ thread2IsAlive = false; System.out.println(“Thread2 : dead); } }while(thread1IsAlive() || thread2IsAlive() ) ; } } class MyThread extends Thread({ static String message[] = {“Java”, “is”, “portable”,”robust”,”and”, “platform independent”}; String threadName; public MyThread(String name){ threadName = name; } public void run{ SynchornizedOutput.displayist(getName, message); } void randomWait(){ try{ sleep((long)(3000* Math.random()); }catch(InterruptedException e){ System.out.println(“Interrupted”); } } }
class SynchronizedOutput{ public static void displayList(String name, String list[]) { for(int i=0; i<list.length ; i++{ MyThread t = (MyThread) Thread.currentThread(): t.randomWait(); System.out.println(name+list[i]); } } } Check the output is not synchronized. Now repeat the execution of the above program by just adding the synchronized keyword in displayList() method declaration. public static synchronized void displayList(String name, String list[]){… Now check the output again. Declaring the displayList() method as synchronized will not allow the second thread to enter this method until the first completes executing it. So the output is also synchronized. Synchronized blocks: Applying synchronized to a method will not work in all cases. For example, we want to call API’s of some class, which are not synchronized methods and now there is no possibility of adding the synchronized keyword. In such cases we can use the synchronized blocks. Syntax: synchronized(object){ statements to be synchronized………. } Until the current thread completes the block execution, other calls cannot be made for the members of the synchronized objects class.
Inter thread communication: The synchronization between threads can be obtained more efficiently by using inter thread communication. The communication increases the CPU usage by notifying the threads that are in the waiting state for long time. For example in the Producer consumer problem the producer has to produce the items and then the consumer has to consume it. If there is no synchronization the producer may produce the items without the consumer consuming it or the producer may produce items without the consumer or the consumer may consume the same item.
So using we need synchronization for producer and consumer to not to enter the monitor while one is executing in it and we need communication between threads so that the output Inter thread communication can be achieved by using the methods wait(), notify() and notifyAll() of object class. Ex: class ItemQueue{ int n; boolean itemProduced = false; synchronized int get(){ if( ! itemProduced ){ try{ wait(); }catch(InterruptedException ie){ System.out.println(ie.getMessage()); } } itemProduced = false; System.out.println(“Consumed “+n); notify(); return n; } } synchronized void put(int item){ if( itemProduced ){ try{ wait(); }catch(InterruptedException ie){ System.out.println(ie.getMessage()); } } n = item; itemProduced = true; System.out.println(“Produced “+n); notify(); } } } class Producer implements Runnable{ ItemQueue q;
public Producer(ItemQueue q){ this.q = q; Thread t = new Thread(this, “Producer”); t.start(); } public void run(){ int n=0; while(true){ q.put(n++); } } } class Consumer implements Runnable{ ItemQueue q; public Consumer(ItemQueue q){ this.q = q; Thread t = new Thread(this, “Consumer”); t.start(); } public void run(){ while(true){ q.get( ); } } } class MainClass{ public static void main(String args[]){ ItemQueue q = new ItemQueue(); Producer p = new Producer(q); Consumer c = new Consumer(q); } } wait() - The thread which calls wait() method will go to the waiting/sleep state until some other thread will go to run state and calls the notify() method. notify() – The thread that calls this method will notify the other waiting thread for the monitor. notifyAll - The thread that calls this method will notify all the other waiting threads that are in waiting state for the monitor.
Daemon Threads: A daemon thread is a thread that executes in the background and provides services to the other threads. It typically executes a continuous loop of instructions that wait for a service request, perform the service, and wait for the next service request. Daemon threads continue to execute until there are no more threads for which services can be provided. At this time daemon thread die and the java interpreter terminates its execution. Any thread can be changed to a daemon by setDaemon() method. The garbage collector is the example of a daemon thread.
DeadLocks: When two threads have circular dependency on a pair of synchronized objects, then a deadlock occurs as both the threads will be in continuous waiting state. class One { public synchronized void callA(){ try{ System.out.println(“In callA method of Thread1 class”); Thread.sleep(2000); }catch(InterruptedException e){ } } } class Two { public synchronized void callB(){ try{ System.out.println(“In callB method of Thread2 class”); Thread.sleep(2000); }catch(InterruptedException e){ } } } class MainClass implements Runnable{ One o1; Two o2; public MainClass (){ o1 = new One(): o2 = new Two(): Thread t = new Thread(this, “ ”); t.start(); o1.callB(): }
public void run(){ o2.callA(); } public static void main(String args[]){ MainClass mainClass = new MainClass(); } }
Thread Groups: Thread groups are the objects that consists of a collection of threads. Every thread is a member of a unique thread group. Thread groups are used to invoke methods that apply to the threads in the thread group. Ex: ThreadGroup tg = new ThreadGroup(“GroupName); Thread t1= new Thread(tg, “Thread1”); Thread t2= new Thread(tg, “Thread2”); Thread t3= new Thread(tg, “Thread3”); Thread t4= new Thread(tg, “Thread4”); Instead of calling start/stop methods individually on each thread, we can do it on the thread group tg.start(); tg.stop(); tg.setDaemon();…etc