UNIT-4
Exception handling and Multi-threaded
            programming
   4.1 Describe sources of errors
• Programming errors can be categorized into
  three types:
1. syntax error
2. runtime errors
3. logic errors
1. Syntax Errors
• Errors that are detected by the compiler are called syntax
    errors or compile errors.
• Syntax errors result from errors in code construction, such as
    mistyping a keyword, omitting some necessary punctuation, or
    using an opening brace without a corresponding closing brace.
• These errors are usually easy to detect because the compiler
    tells you where they are and what caused them.
• For example, the following program has a syntax error:
public class JavaDemo {
   public static main(String[] args) {
     System.out.println("Hello World Example);
   }
}
2. Runtime Errors
• Runtime errors are errors that cause a program to terminate abnormally.
• They occur while a program is running if the environment detects an operation that is
     impossible to carry out.
• Input mistakes typically cause runtime errors.
• An input error occurs when the program is waiting for the user to enter a value, but the
     user enters a value that the program cannot handle.
• For instance, if the program expects to read in a number, but instead the user enters a
     string, this causes data-type errors to occur in the program.
• Another example of runtime errors is division by zero. This happens when the divisor is
     zero for integer divisions. For instance, the following program would cause a runtime
     error:
public class JavaDemo {
   public static void main(String[] args) {
      System.out.println(10/0);
   }
}
Output:
Exception in thread "main" java.lang.ArithmeticException: / by zero at
     com.javaguides.JavaDemo.main(JavaDemo.java:24)
Logic Errors
• Logic errors occur when a program does not perform the way it was intended to. Errors of this
    kind occur for many different reasons.
• For example, suppose you wrote the program to convert Celsius 35 degrees to a Fahrenheit
    degree:
public class JavaDemo {
  public static void main(String[] args) {
     System.out.println("Celsius 35 is Fahrenheit degree ");
     System.out.println((9 / 5) * 35 + 32);
  }
}
• Output:
• Celsius 35 is Fahrenheit degree 67
• You will get Fahrenheit 67 degrees, which is wrong. It should be 95.0. In Java, the division for
    integers is the quotient—the fractional part is truncated—so in Java 9 / 5 is 1. To get the correct
    result, you need to use 9.0 / 5, which results in 1.8.
• Common Errors
• Missing a closing brace, missing a semicolon, missing quotation marks for strings, and
    misspelling names are common errors for new programmers.
• In general, syntax errors are easy to find and easy to correct because the compiler gives
    indications as to where the errors came from and why they are wrong.
• Runtime errors are not difficult to find, either, since the reasons and locations for the errors are
    displayed on the console when the program aborts.
•
               Give advantages of Exception handling
Exception Handling in Java
• The Exception Handling in Java is one of the
  powerful mechanism to handle the runtime errors so that the
  normal flow of the application can be maintained.
• In this tutorial, we will learn about Java exceptions, it's types, and
  the difference between checked and unchecked exceptions.
• What is Exception in Java?
• Dictionary Meaning: Exception is an abnormal condition.
• In Java, an exception is an event that disrupts the normal flow of
  the program. It is an object which is thrown at runtime.
What is Exception Handling?
• Exception Handling is a mechanism to handle runtime errors such
  as ClassNotFoundException, IOException, SQLException,
  RemoteException, etc.
Advantage of Exception Handling:
•   The core advantage of exception handling is to maintain the normal flow of the
    application. An exception normally disrupts the normal flow of the application;
    that is why we need to handle exceptions.
•   Let's consider a scenario:
•   statement 1;
•   statement 2;
•   statement 3;
•   statement 4;
•   statement 5;//exception occurs
•   statement 6;
•   statement 7;
•   statement 8;
•   statement 9;
•   statement 10;
•   Suppose there are 10 statements in a Java program and an exception occurs at
    statement 5; the rest of the code will not be executed, i.e., statements 6 to 10 will
    not be executed.
•   However, when we perform exception handling, the rest of the statements will be
    executed. That is why we use exception handling in Java.
Hierarchy of Java Exception classes
•   The java.lang.Throwable class is the root class of Java Exception hierarchy inherited by
    two subclasses: Exception and Error. The hierarchy of Java Exception classes is given
    below:
 Explain types of exceptions Checked and Unchecked
• There are mainly two types of exceptions:
  checked and unchecked. An error is considered as
  the unchecked exception.
• However, according to Oracle, there are three
  types of exceptions namely:
  1. Checked Exception
  2. Unchecked Exception
  3. Error
1) Checked Exception
• The classes that directly inherit the Throwable class except
   Runtime Exception and Error are known as checked exceptions.
• For example, IOException, SQLException, etc.
• Checked exceptions are checked at compile-time.
2) Unchecked Exception
• The classes that inherit the RuntimeException are known as
   unchecked exceptions.
• For example, ArithmeticException, NullPointerException,
   ArrayIndexOutOfBoundsException, etc.
• Unchecked exceptions are not checked at compile-time, but they
   are checked at runtime.
3) Error
• Error is irrecoverable.
• Some example of errors are OutOfMemoryError,
   VirtualMachineError, AssertionError etc.
         Write sample programs to make use of Try, Catch,
                     Finally, Throw, Throws
• Java provides five keywords that are used to handle the exception. The following
  table describes each.
  Keyword     Description
 try          The "try" keyword is used to specify a block where we should place an
              exception code. It means we can't use try block alone. The try block must be
              followed by either catch or finally.
 catch        The "catch" block is used to handle the exception. It must be preceded by try
              block which means we can't use catch block alone. It can be followed by
              finally block later.
 finally      The "finally" block is used to execute the necessary code of the program. It is
              executed whether an exception is handled or not.
 throw        The "throw" keyword is used to throw an exception.
 throws       The "throws" keyword is used to declare exceptions. It specifies that there
              may occur an exception in the method. It doesn't throw an exception. It is
              always used with method signature.
Java Exception Handling Example:
•     Let's see an example of Java Exception Handling in which we are using a try-catch
      statement to handle the exception.
public class JavaExceptionExample{
  public static void main(String args[]){
   try{
      //code that may raise exception
      int data=100/0;
   }catch(ArithmeticException e)
   {
      System.out.println(e);
    }
   //rest code of the program
   System.out.println("rest of the code...");
  }
}
Output:
Exception in thread main java.lang.ArithmeticException:/ by zero
rest of the code...
Java try-catch block:
Java try block
• Java try block is used to enclose the code that might throw an exception. It must be used within the
    method.
• If an exception occurs at the particular statement in the try block, the rest of the block code will not
    execute. So, it is recommended not to keep the code in try block that will not throw an exception.
• Java try block must be followed by either catch or finally block.
Syntax of Java try-catch
try{
//code that may throw an exception
}catch(Exception_class_Name ref){}
Syntax of try-finally block
try{
//code that may throw an exception
}finally{}
Java catch block:
•   Java catch block is used to handle the Exception by declaring the type of exception within the
    parameter.
•   The declared exception must be the parent class exception ( i.e., Exception) or the generated
    exception type.
•   However, the good approach is to declare the generated type of exception.
•   The catch block must be used after the try block only. You can use multiple catch block with a single
    try block.
Internal Working of Java try-catch block
• The JVM firstly checks whether the exception is
  handled or not.
• If exception is not handled, JVM provides a
  default exception handler that performs the
  following tasks:
  1. Prints out exception description.
  2. Prints the stack trace (Hierarchy of methods where
     the exception occurred).
  3. Causes the program to terminate.
• But if the application programmer handles the
  exception, the normal flow of the application is
  maintained, i.e., rest of the code is executed.
Problem without exception handling:
• Let's try to understand the problem if we don't use a try-catch block.
• Example 1
• TryCatchExample1.java
public class TryCatchExample1 {
    public static void main(String[] args) {
        int data=50/0; //may throw exception
        System.out.println("rest of the code");
}
Output:
Exception in thread "main" java.lang.ArithmeticException: / by zero
• As displayed in the above example, the rest of the code is not executed (in such case,
   the rest of the code statement is not printed).
• There might be 100 lines of code after the exception. If the exception is not handled, all the
   code below the exception won't be executed.
Solution by exception handling
•    Let's see the solution of the above problem by a java try-catch block.
Example 2
TryCatchExample2.java
public class TryCatchExample2 {
    public static void main(String[] args) {
      try
      {
      int data=50/0; //may throw exception
      }
        //handling the exception
      catch(ArithmeticException e)
      {
        System.out.println(e);
      }
      System.out.println("rest of the code");
    }
}
Output:
java.lang.ArithmeticException: / by zero
 rest of the code
      Explain concept of multi-catch statements with
                         example
Java Multi-catch block
• A try block can be followed by one or more catch blocks.
• Each catch block must contain a different exception handler.
• So, if you have to perform different tasks at the occurrence
  of different exceptions, use java multi-catch block.
Points to remember
• At a time only one exception occurs and at a time only one
  catch block is executed.
• All catch blocks must be ordered from most specific to most
  general, i.e. catch for ArithmeticException must come
  before catch for Exception.
Flowchart of Multi-catch Block
Example 1
• Let's see a simple example of java multi-catch block.
MultipleCatchBlock1.java
public class MultipleCatchBlock1 {
  public static void main(String[] args) {
      try{
         int a[]=new int[5];
         a[5]=30/0;
        }
        catch(ArithmeticException e)
           {
            System.out.println("Arithmetic Exception occurs");
           }
        catch(ArrayIndexOutOfBoundsException e)
           {
            System.out.println("ArrayIndexOutOfBounds Exception occurs");
           }
        catch(Exception e)
           {
            System.out.println("Parent Exception occurs");
           }
        System.out.println("rest of the code");
  }
}
Output:
Arithmetic Exception occurs
Example 2:
public class MultipleCatchBlock4 {
    public static void main(String[] args) {
        try{
           String s=null;
           System.out.println(s.length());
          }
          catch(ArithmeticException e)
             {
              System.out.println("Arithmetic Exception occurs");
             }
          catch(ArrayIndexOutOfBoundsException e)
             {
              System.out.println("ArrayIndexOutOfBounds Exception occurs");
             }
          catch(Exception e)
             {
              System.out.println("Parent Exception occurs");
             }
          System.out.println("rest of the code");
    }
}
Output:
Parent Exception occurs
   Explain how to write nested try in exception
             handling with example
Java Nested try block
• In Java, using a try block inside another try block is permitted. It
  is called as nested try block.
• Every statement that we enter a statement in try block, context
  of that exception is pushed onto the stack.
• For example, the inner try block can be used to
  handle ArrayIndexOutOfBoundsException while the outer try
  block can handle the ArithemeticException (division by zero).
Why use nested try block
• Sometimes a situation may arise where a part of a block may
  cause one error and the entire block itself may cause another
  error.
• In such cases, exception handlers have to be nested.
Syntax:
....
//main try block
try
{
  statement 1;
  statement 2;
//try catch block within another try block
  try
  {
     statement 3;
     statement 4;
//try catch block within nested try block
     try
     {
       statement 5;
       statement 6;
   }
     catch(Exception e2)
     {
//exception message
     }
    }
    catch(Exception e1)
    {
//exception message
    }
}
//catch block of parent (outer) try block
catch(Exception e3)
{
//exception message
}
....
Example 1                                                 //catch block of inner try block 2
•     Let's see an example where we place a try block     catch(ArrayIndexOutOfBoundsException e)
      within another try block for two different          {
      exceptions.                                           System.out.println(e);
public class NestedTryBlock{                              }
public static void main(String args[]){
//outer try block
 try{                                                     System.out.println("other statement");
 //inner try block 1                                     }
   try{                                                  //catch block of outer try block
    System.out.println("going to divide by 0");          catch(Exception e)
    int b =39/0;                                         {
  }                                                        System.out.println("handled the exception (outer ca
                                                             tch)");
   //catch block of inner try block 1
                                                         }
   catch(ArithmeticException e)
   {
                                                          System.out.println("normal flow..");
     System.out.println(e);
                                                         }
   }
                                                        }
   //inner try block 2
                                                        Output:
   try{
   int a[]=new int[5];
  //assigning the value out of array bounds
    a[5]=4;
    }
• When any try block does not have a catch block
  for a particular exception, then the catch block
  of the outer (parent) try block are checked for
  that exception, and if it matches, the catch block
  of outer try block is executed.
• If none of the catch block specified in the code is
  unable to handle the exception, then the Java
  runtime system will handle the exception. Then
  it displays the system generated message for
  that exception.
              Describe built in exceptions
• Java defines several types of exceptions that relate
  to its various class libraries.
• Java also allows users to define their own
  exceptions.
Built-in exceptions:
•     These are the exceptions that are available in Java libraries. These exceptions are suitable to explain certain
      error situations. Below is the list of important built-in exceptions in Java.
1.      ArithmeticException: It is thrown when an exceptional condition has occurred in an arithmetic operation.
2.      ArrayIndexOutOfBoundsException: It is thrown to indicate that an array has been accessed with an illegal
        index. The index is either negative or greater than or equal to the size of the array.
3.      ClassNotFoundException: This Exception is raised when we try to access a class whose definition is not
        found
4.      FileNotFoundException: This Exception is raised when a file is not accessible or does not open.
5.      IOException: It is thrown when an input-output operation failed or interrupted
6.      InterruptedException: It is thrown when a thread is waiting, sleeping, or doing some processing, and it is
        interrupted.
7.      NoSuchFieldException: It is thrown when a class does not contain the field (or variable) specified
8.      NoSuchMethodException: It is thrown when accessing a method that is not found.
9.      NullPointerException: This exception is raised when referring to the members of a null object. Null
        represents nothing
10.     NumberFormatException: This exception is raised when a method could not convert a string into a
        numeric format.
11.     RuntimeException: This represents an exception that occurs during runtime.
12.     StringIndexOutOfBoundsException: It is thrown by String class methods to indicate that an index is either
        negative or greater than the size of the string
13.     IllegalArgumentException : This exception will throw the error or error statement when the method
        receives an argument which is not accurately fit to the given relation or condition. It comes under the
        unchecked exception.
14.     IllegalStateException : This exception will throw an error or error message when the method is not
        accessed for the particular operation in the application. It comes under the unchecked exception.
                      Describe multithreading
•   Multithreading in Java
•   Multithreading in Java is a process of executing multiple threads
    simultaneously.
•   A thread is a lightweight sub-process, the smallest unit of processing.
    Multiprocessing and multithreading, both are used to achieve multitasking.
•   However, we use multithreading than multiprocessing because threads use a
    shared memory area. They don't allocate separate memory area so saves
    memory, and context-switching between the threads takes less time than
    process.
•   Java Multithreading is mostly used in games, animation, etc.
•   Advantages of Java Multithreading
•   1) It doesn't block the user because threads are independent and you can
    perform multiple operations at the same time.
•   2) You can perform many operations together, so it saves time.
•   3) Threads are independent, so it doesn't affect other threads if an exception
    occurs in a single thread.
Multitasking
• Multitasking is a process of executing multiple tasks simultaneously. We
  use multitasking to utilize the CPU. Multitasking can be achieved in two
  ways:
   1.   Process-based Multitasking (Multiprocessing)
   2.   Thread-based Multitasking (Multithreading)
1) Process-based Multitasking (Multiprocessing)
• Each process has an address in memory. In other words, each process
   allocates a separate memory area.
• A process is heavyweight.
• Cost of communication between the process is high.
• Switching from one process to another requires some time for saving and
   loading registers, memory maps, updating lists, etc.
2) Thread-based Multitasking (Multithreading)
• Threads share the same address space.
• A thread is lightweight.
• Cost of communication between the thread is low.
• Note: At least one process is required for each thread.
What is Thread in java
• A thread is a lightweight subprocess,
  the smallest unit of processing. It is a
  separate path of execution.
• Threads are independent. If there
  occurs exception in one thread, it
  doesn't affect other threads. It uses
  a shared memory area.
• As shown in the below figure, a
  thread is executed inside the
  process.
• There is context-switching between
  the threads.
• There can be multiple processes
  inside the OS, and one process can
  have multiple threads.
• Note: At a time one thread is
  executed only.
Explain Thread life cycle and states
• Life cycle of a Thread (Thread States)
• In Java, a thread always exists in any one of
  the following states. These states are:
• New
• Active
• Blocked / Waiting
• Timed Waiting
• Terminated
•   New: Whenever a new thread is created, it is always in the new state. For a thread in the new state, the code has
    not been run yet and thus has not begun its execution.
•   Active: When a thread invokes the start() method, it moves from the new state to the active state.
•   The active state contains two states within it: one is runnable, and the other is running.
•   Runnable: A thread, that is ready to run is then moved to the runnable state.
•   In the runnable state, the thread may be running or may be ready to run at any given instant of time.
•   It is the duty of the thread scheduler to provide the thread time to run, i.e., moving the thread the running state.
•   A program implementing multithreading acquires a fixed slice of time to each individual thread.
•   Each and every thread runs for a short span of time and when that allocated time slice is over, the thread
    voluntarily gives up the CPU to the other thread, so that the other threads can also run for their slice of time.
•   Whenever such a scenario occurs, all those threads that are willing to run, waiting for their turn to run, lie in the
    runnable state.
•   In the runnable state, there is a queue where the threads lie.
•   Running: When the thread gets the CPU, it moves from the runnable to the running state. Generally, the most
    common change in the state of a thread is from runnable to running and again back to runnable.
•   Blocked or Waiting: Whenever a thread is inactive for a span of time (not permanently) then, either the thread is
    in the blocked state or is in the waiting state.
•   Terminated: A thread reaches the termination state because of the following reasons:
      – When a thread has finished its job, then it exists or terminates normally.
      – Abnormal termination: It occurs when some unusual events such as an unhandled exception or
            segmentation fault.
•   A terminated thread means the thread is no more in the system. In other words, the thread is dead, and there is
    no way one can respawn (active after kill) the dead thread.
The following diagram shows the different states involved in the life cycle of a
thread.
  Explain how to Creating single thread with example program
How to create a thread in Java
• There are two ways to create a thread:
   1. By extending Thread class
   2. By implementing Runnable interface.
Thread class:
• Thread class provide constructors and methods to create
  and perform operations on a thread.Thread class extends
  Object class and implements Runnable interface.
Commonly used Constructors of Thread class:
• Thread()
• Thread(String name)
• Thread(Runnable r)
• Thread(Runnable r,String name)
Commonly used methods of Thread class:
1.    public void run(): is used to perform action for a thread.
2.    public void start(): starts the execution of the thread.JVM calls the run() method on the thread.
3.    public void sleep(long miliseconds): Causes the currently executing thread to sleep (temporarily cease
      execution) for the specified number of milliseconds.
4.    public void join(): waits for a thread to die.
5.    public void join(long miliseconds): waits for a thread to die for the specified miliseconds.
6.    public int getPriority(): returns the priority of the thread.
7.    public int setPriority(int priority): changes the priority of the thread.
8.    public String getName(): returns the name of the thread.
9.    public void setName(String name): changes the name of the thread.
10.   public Thread currentThread(): returns the reference of currently executing thread.
11.   public int getId(): returns the id of the thread.
12.   public Thread.State getState(): returns the state of the thread.
13.   public boolean isAlive(): tests if the thread is alive.
14.   public void yield(): causes the currently executing thread object to temporarily pause and allow other threads to
      execute.
15.   public void suspend(): is used to suspend the thread(depricated).
16.   public void resume(): is used to resume the suspended thread(depricated).
17.   public void stop(): is used to stop the thread(depricated).
18.   public boolean isDaemon(): tests if the thread is a daemon thread.
19.   public void setDaemon(boolean b): marks the thread as daemon or user thread.
20.   public void interrupt(): interrupts the thread.
21.   public boolean isInterrupted(): tests if the thread has been interrupted.
22.   public static boolean interrupted(): tests if the current thread has been interrupted.
Runnable interface:
• The Runnable interface should be implemented by any
  class whose instances are intended to be executed by a
  thread.
• Runnable interface have only one method named run().
• public void run(): is used to perform action for a thread.
• Starting a thread:
• The start() method of Thread class is used to start a newly
  created thread.
• It performs the following tasks:
   1. A new thread starts(with new callstack).
   2. The thread moves from New state to the Runnable state.
   3. When the thread gets a chance to execute, its target run()
      method will run.
1) Java Thread Example by extending Thread class
class Multi extends Thread{
public void run(){
System.out.println("thread is running...");
}
public static void main(String args[]){
Multi t1=new Multi();
t1.start();
 }
}
Output:
thread is running...
2) Java Thread Example by implementing Runnable interface
class Multi3 implements Runnable{
public void run(){
System.out.println("thread is running...");
}
public static void main(String args[]){
Multi3 m1=new Multi3();
Thread t1 =new Thread(m1); // Using the constructor Thread(Runnable r)
t1.start();
 }
}
Output:
thread is running...