Unit - 5
Multithreading in java
In Java, multithreading is the process of running several threads at the same time.
A thread is the smallest unit of processing and is a lightweight sub-process. Multitasking is accomplished through the use of multiprocessing and multithreading.
Because threads share memory, we employ multithreading rather than multiprocessing. They conserve memory by not allocating a separate memory space, and context-switching between threads takes less time than processing.
Multithreading in Java is typically utilized in gaming, animation, and other similar applications.
Because Java is a multi-threaded programming language, we can use it to create multi-threaded programs. A multi-threaded program is made up of two or more portions that can operate in parallel, each of which can tackle a distinct task at the same time, maximizing the use of available resources, especially when your computer has several CPUs.
Multitasking is defined as the sharing of common processing resources, such as a CPU, by many processes. Multi-threading extends the concept of multitasking into programs by allowing you to divide certain operations within a single app into several threads. Each thread can execute in its own thread. Not only does the operating system split processing time among distinct apps, but it also divides it among each thread within an application.
Multi-threading allows you to write software in which multiple activities can run at the same time.
The Java Thread Model
The Java run-time system depends on threads for many things, and all the class libraries are designed with multithreading in mind. In fact, Java uses threads to enable the entire environment to be asynchronous. This helps reduce inefficiency by preventing the waste of CPU cycles.
The value of a multithreaded environment is best understood in contrast to its counterpart. Single-threaded systems use an approach called an event loop with polling. In this model, a single thread of control runs in an infinite loop, polling a single event queue to decide what to do next. Once this polling mechanism returns with, say, a signal that a network file is ready to be read, then the event loop dispatches control to the appropriate event handler. Until this event handler returns, nothing else can happen in the program. This wastes CPU time. It can also result in one part of a program dominating the system and preventing any other events from being processed. In general, in a single-threaded environment, when a thread blocks (that is, suspends execution) because it is waiting for some resource, the entire program stops running.
The benefit of Java’s multithreading is that the main loop/polling mechanism is eliminated. One thread can pause without stopping other parts of your program. For example, the idle time created when a thread reads data from a network or waits for user input can be utilized elsewhere. Multithreading allows animation loops to sleep for a second between each frame without causing the whole system to pause. When a thread blocks in a Java program, only the single thread that is blocked pauses. All other threads continue to run.
As most readers know, over the past few years, multi-core systems have become commonplace. Of course, single-core systems are still in widespread use. It is important to understand that Java’s multithreading features work in both types of systems. In a single-core system, concurrently executing threads share the CPU, with each thread receiving a slice of CPU time. Therefore, in a single-core system, two or more threads do not actually run at the same time, but idle CPU time is utilized. However, in multi-core systems, it is possible for two or more threads to actually execute simultaneously. In many cases, this can further improve program efficiency and increase the speed of certain operations.
Threads exist in several states. Here is a general description. A thread can be running. It can be ready to run as soon as it gets CPU time. A running thread can be suspended, which temporarily halts its activity. A suspended thread can then be resumed, allowing it to pick up where it left off. A thread can be blocked when waiting for a resource. At any time, a thread can be terminated, which halts its execution immediately. Once terminated, a thread cannot be resumed.
Life Cycle of a Thread
A thread goes through various stages in its life cycle. For example, a thread is born, started, runs, and then dies. The following diagram shows the complete life cycle of a thread.
Fig 1 - The complete life cycle of a thread
Following are the stages of the life cycle −
● New − A new thread begins its life cycle in the new state. It remains in this state until the program starts the thread. It is also referred to as a born thread.
● Runnable − After a newly born thread is started, the thread becomes runnable. A thread in this state is considered to be executing its task.
● Waiting − Sometimes, a thread transitions to the waiting state while the thread waits for another thread to perform a task. A thread transitions back to the runnable state only when another thread signals the waiting thread to continue executing.
● Timed Waiting − A runnable thread can enter the timed waiting state for a specified interval of time. A thread in this state transitions back to the runnable state when that time interval expires or when the event it is waiting for occurs.
● Terminated (Dead) − A runnable thread enters the terminated state when it completes its task or otherwise terminates.
Thread Methods
Following is the list of important methods available in the Thread class.
Sr.No. | Method & Description |
1 | Public void start() Starts the thread in a separate path of execution, then invokes the run() method on this Thread object. |
2 | Public void run() If this Thread object was instantiated using a separate Runnable target, the run() method is invoked on that Runnable object. |
3 | Public final void setName(String name) Changes the name of the Thread object. There is also a getName() method for retrieving the name. |
4 | Public final void setPriority(int priority) Sets the priority of this Thread object. The possible values are between 1 and 10. |
5 | Public final void setDaemon(boolean on) A parameter of true denotes this Thread as a daemon thread. |
6 | Public final void join(long millisec) The current thread invokes this method on a second thread, causing the current thread to block until the second thread terminates or the specified number of milliseconds passes. |
7 | Public void interrupt() Interrupts this thread, causing it to continue execution if it was blocked for any reason. |
8 | Public final boolean isAlive() Returns true if the thread is alive, which is any time after the thread has been started but before it runs to completion. |
The previous methods are invoked on a particular Thread object. The following methods in the Thread class are static. Invoking one of the static methods performs the operation on the currently running thread.
Sr.No. | Method & Description |
1 | Public static void yield() Causes the currently running thread to yield to any other threads of the same priority that are waiting to be scheduled. |
2 | Public static void sleep(long millisec) Causes the currently running thread to block for at least the specified number of milliseconds. |
3 | Public static boolean holdsLock(Object x) Returns true if the current thread holds the lock on the given Object. |
4 | Public static Thread currentThread() Returns a reference to the currently running thread, which is the thread that invokes this method. |
5 | Public static void dumpStack() Prints the stack trace for the currently running thread, which is useful when debugging a multithreaded application. |
Example
The following ThreadClassDemo program demonstrates some of these methods of the Thread class. Consider a class DisplayMessage which implements Runnable −
// File Name : DisplayMessage.java
// Create a thread to implement Runnable
Public class DisplayMessage implements Runnable {
Private String message;
Public DisplayMessage(String message) {
This.message = message;
}
Public void run() {
While(true) {
System.out.println(message);
}
}
}
Following is another class which extends the Thread class −
// File Name : GuessANumber.java
// Create a thread to extend Thread
Public class GuessANumber extends Thread {
Private int number;
Public GuessANumber(int number) {
This.number = number;
}
Public void run() {
Int counter = 0;
Int guess = 0;
Do {
Guess = (int) (Math.random() * 100 + 1);
System.out.println(this.getName() + " guesses " + guess);
Counter++;
} while(guess != number);
System.out.println("** Correct!" + this.getName() + "in" + counter + "guesses.**");
}
}
Following is the main program, which makes use of the above-defined classes −
// File Name : ThreadClassDemo.java
Public class ThreadClassDemo {
Public static void main(String [] args) {
Runnable hello = new DisplayMessage("Hello");
Thread thread1 = new Thread(hello);
Thread1.setDaemon(true);
Thread1.setName("hello");
System.out.println("Starting hello thread...");
Thread1.start();
Runnable bye = new DisplayMessage("Goodbye");
Thread thread2 = new Thread(bye);
Thread2.setPriority(Thread.MIN_PRIORITY);
Thread2.setDaemon(true);
System.out.println("Starting goodbye thread...");
Thread2.start();
System.out.println("Starting thread3...");
Thread thread3 = new GuessANumber(27);
Thread3.start();
Try {
Thread3.join();
} catch (InterruptedException e) {
System.out.println("Thread interrupted.");
}
System.out.println("Starting thread4...");
Thread thread4 = new GuessANumber(75);
Thread4.start();
System.out.println("main() is ending...");
}
}
This will produce the following result. You can try this example again and again and you will get a different result every time.
Output
Starting hello thread...
Starting goodbye thread...
Hello
Hello
Hello
Hello
Hello
Hello
Goodbye
Goodbye
Goodbye
Goodbye
Goodbye
.......
Key takeaway
Multithreading is the process of running several threads at the same time.
Multithreading in Java is typically utilized in gaming, animation, and other similar applications.
A thread goes through various stages in its life cycle. For example, a thread is born, started, runs, and then dies. The following diagram shows the complete life cycle of a thread.
Java.lang. Runnable is an interface that a class must implement if its instances are to be executed by a thread. Subclass Thread and implement Runnable are two techniques to start a new Thread. When a task can be accomplished by overriding simply the run() function of Runnable, there is no need to subclass Thread.
Steps to create a new Thread using Runnable
● Make a Runnable implementer and use it to call the run() method.
● Create a Thread object and pass the implementer to it; Thread has a function Object() { [native code] } that takes Runnable objects.
● Invoke the Thread instance's start() method, which runs the implementer's run() method inside. When you call start(), it generates a new Thread that runs the code you wrote in run ().
When you call run() directly, it does not create and start a new Thread; instead, it continues to execute in the same thread. To start a new line of execution, call start() on the thread.
Example
Public class RunnableDemo {
Public static void main(String[] args)
{
System.out.println("Main thread is- "
+ Thread.currentThread().getName());
Thread t1 = new Thread(new RunnableDemo().new RunnableImpl());
t1.start();
}
Private class RunnableImpl implements Runnable {
Public void run()
{
System.out.println(Thread.currentThread().getName()
+ ", executing run() method!");
}
}
}
Output
Main thread is- main
Thread-0, executing run() method!
The main thread executes the main method, while executing start on RunnableImpl produces and starts a new thread, Thread-0.
The Thread Class and the Runnable Interface
Java’s multithreading system is built upon the Thread class, its methods, and its companion interface, Runnable. Thread encapsulates a thread of execution. Since you can’t directly refer to the ethereal state of a running thread, you will deal with it through its proxy, the Thread instance that spawned it. To create a new thread, your program will either extend Thread or implement the Runnable interface.
The Thread class defines several methods that help manage threads. Several of those used is shown here:
Fig 2 - Thread class defines several methods
Thus far, all the examples in this book have used a single thread of execution. The remainder of this chapter explains how to use Thread and Runnable to create and manage threads, beginning with the one thread that all Java programs have: the main thread.
Create a Thread by Implementing a Runnable Interface
If your class is intended to be executed as a thread then you can achieve this by implementing a Runnable interface. You will need to follow three basic steps −
Step 1
As a first step, you need to implement a run() method provided by a Runnable interface. This method provides an entry point for the thread and you will put your complete business logic inside this method. Following is a simple syntax of the run() method −
Public void run( )
Step 2
As a second step, you will instantiate a Thread object using the following constructor −
Thread(Runnable threadObj, String threadName);
Where, threadObj is an instance of a class that implements the Runnable interface and threadName is the name given to the new thread.
Step 3
Once a Thread object is created, you can start it by calling start() method, which executes a call to run( ) method. Following is a simple syntax of start() method −
Void start();
Example
Here is an example that creates a new thread and starts running it −
Class RunnableDemo implements Runnable {
Private Thread t;
Private String threadName;
RunnableDemo( String name) {
ThreadName = name;
System.out.println("Creating " + threadName );
}
Public void run() {
System.out.println("Running " + threadName );
Try {
For(int i = 4; i > 0; i--) {
System.out.println("Thread: " + threadName + ", " + i);
// Let the thread sleep for a while.
Thread.sleep(50);
}
} catch (InterruptedException e) {
System.out.println("Thread " + threadName + " interrupted.");
}
System.out.println("Thread " + threadName + " exiting.");
}
Public void start () {
System.out.println("Starting " + threadName );
If (t == null) {
t = new Thread (this, threadName);
t.start ();
}
}
}
Public class TestThread {
Public static void main(String args[]) {
RunnableDemo R1 = new RunnableDemo( "Thread-1");
R1.start();
RunnableDemo R2 = new RunnableDemo( "Thread-2");
R2.start();
}
}
This will produce the following result −
Output
Creating Thread-1
Starting Thread-1
Creating Thread-2
Starting Thread-2
Running Thread-1
Thread: Thread-1, 4
Running Thread-2
Thread: Thread-2, 4
Thread: Thread-1, 3
Thread: Thread-2, 3
Thread: Thread-1, 2
Thread: Thread-2, 2
Thread: Thread-1, 1
Thread: Thread-2, 1
Thread Thread-1 exiting.
Thread Thread-2 exiting.
Key takeaway
Java.lang. Runnable is an interface that a class must implement if its instances are to be executed by a thread. Subclass Thread and implement Runnable are two techniques to start a new Thread.
Synchronization in java is the capability to control the access of multiple threads to any shared resource.
Java Synchronization is better option where we want to allow only one thread to access the shared resource.
When we start two or more threads in a program, it's possible that numerous threads will try to access the same resource, resulting in unexpected results due to concurrency difficulties. For example, if multiple threads try to write to the same file at the same time, the data may be corrupted because one of the threads can override data, or while one thread is opening and another is closing the same file.
As a result, it's necessary to synchronize many threads' actions and ensure that only one thread can access the resource at any given time. This is accomplished through the use of monitors. In Java, each object has its own monitor, which a thread can lock or unlock. On a display, only one thread can retain a lock at a time.
Using synchronized blocks, the Java programming language makes it relatively easy to create threads and synchronize their tasks. Within this block, you retain shared resources. The general form of the synchronized statement is as follows:
Syntax
Synchronized(objectidentifier)
{
// Access shared variables and other shared resources
}
The objec tidentifier is a reference to an object whose lock corresponds to the monitor represented by the synchronized statement. Now we'll look at two different ways to print a counter using two distinct threads. When threads are not synchronized, they publish counter values that are out of order, but when we print counter inside a synchronized() block, it prints counters that are very much in order for both threads.
Multithreading Example with synchronization
Class PrintDemo {
Public void printCount() {
Try {
For(int i = 5; i > 0; i--) {
System.out.println("Counter --- " + i );
}
} catch (Exception e) {
System.out.println("Thread interrupted.");
}
}
}
Class ThreadDemo extends Thread {
Private Thread t;
Private String threadName;
PrintDemo PD;
ThreadDemo( String name, PrintDemo pd) {
ThreadName = name;
PD = pd;
}
Public void run() {
Synchronized(PD) {
PD.printCount();
}
System.out.println("Thread " + threadName + " exiting.");
}
Public void start () {
System.out.println("Starting " + threadName );
If (t == null) {
t = new Thread (this, threadName);
t.start ();
}
}
}
Public class TestThread {
Public static void main(String args[]) {
PrintDemo PD = new PrintDemo();
ThreadDemo T1 = new ThreadDemo( "Thread - 1 ", PD );
ThreadDemo T2 = new ThreadDemo( "Thread - 2 ", PD );
T1.start();
T2.start();
// wait for threads to end
Try {
T1.join();
T2.join();
} catch ( Exception e) {
System.out.println("Interrupted");
}
}
}
Output
Starting Thread - 1
Starting Thread - 2
Counter --- 5
Counter --- 4
Counter --- 3
Counter --- 2
Counter --- 1
Thread Thread - 1 exiting.
Counter --- 5
Counter --- 4
Counter --- 3
Counter --- 2
Counter --- 1
Thread Thread - 2 exiting.
Why use Synchronization
The synchronization is mainly used to
- To prevent thread interference.
- To prevent consistency problem.
Types of Synchronization
There are two types of synchronization
- Process Synchronization
- Thread Synchronization
Understanding the problem without Synchronization
In this example, there is no synchronization, so output is inconsistent. Let's see the example:
- Class Table{
- Void printTable(int n){//method not synchronized
- For(int i=1;i<=5;i++){
- System.out.println(n*i);
- Try{
- Thread.sleep(400);
- }catch(Exception e){System.out.println(e);}
- }
- }
- }
- Class MyThread1 extends Thread{
- Table t;
- MyThread1(Table t){
- This.t=t;
- }
- Public void run(){
- t.printTable(5);
- }
- }
- Class MyThread2 extends Thread{
- Table t;
- MyThread2(Table t){
- This.t=t;
- }
- Public void run(){
- t.printTable(100);
- }
- }
- Class TestSynchronization1{
- Public static void main(String args[]){
- Table obj = new Table();//only one object
- MyThread1 t1=new MyThread1(obj);
- MyThread2 t2=new MyThread2(obj);
- t1.start();
- t2.start();
- }
- }
Output: 5
100
10
200
15
300
20
400
25
500
Java synchronized method
If you declare any method as synchronized, it is known as synchronized method.
Synchronized method is used to lock an object for any shared resource.
When a thread invokes a synchronized method, it automatically acquires the lock for that object and releases it when the thread completes its task.
Key takeaway
Using synchronized blocks, the Java programming language makes it relatively easy to create threads and synchronize their tasks. Within this block, you retain shared resources.
● The Exception Handling in Java is one of the powerful mechanisms to handle the runtime errors so that the normal flow of the application can be maintained.
● 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 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.
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 use exception handling. Let's take 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 your program and there occurs an exception at statement 5, the rest of the code will not be executed i.e. statement 6 to 10 will not be executed. If we perform exception handling, the rest of the statement will be executed. That is why we use exception handling in Java.
Benefits of exception handling
● When an exception occurs, exception handling guarantees that the program's flow is preserved.
● This allows us to identify the different types of faults.
● This allows us to develop error-handling code separately from the rest of the code.
When an exception occurs, exception handling ensures that the program's flow does not break. For example, if a programme has a large number of statements and an exception occurs in the middle of executing some of them, the statements after the exception will not be executed, and the programme will end abruptly.
By handling, we ensure that all of the statements are executed and that the program's flow is not disrupted.
Key takeaway
The Exception Handling in Java is one of the powerful mechanisms to handle the runtime errors so that the normal flow of the application can be maintained.
Hierarchy of Java Exception classes
The java.lang.Throwable class is the root class of Java Exception hierarchy which is inherited by two subclasses: Exception and Error.
All exception and error kinds are subclasses of the hierarchy's root class, Throwable. Exception is in charge of one branch. This class is used for unusual circumstances that user programmes should be aware of. An example of such an exception is the NullPointerException. The Java run-time system (JVM) uses another branch, Error, to identify issues related to the run-time environment (JRE). An example of such an error is StackOverflowError.
A hierarchy of Java Exception classes are given below:
Fig 3 - A hierarchy of Java Exception classes
Types of Java Exceptions
There are mainly two types of exceptions: checked and unchecked. Here, an error is considered as the unchecked exception. According to Oracle, there are three types of exceptions:
- Checked Exception
- Unchecked Exception
- Error
Fig 4 – Exception handling
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:
❖ The classes that directly inherit the Throwable class except RuntimeException and Error are known as checked exceptions.
❖ For example, IOException, SQLException, etc. Checked exceptions are checked at compile-time.
1. ClassNotFoundException: The ClassNotFoundException is a kind of checked exception that is thrown when we attempt to use a class that does not exist.
Checked exceptions are those exceptions that are checked by the Java compiler itself.
2. FileNotFoundException: The FileNotFoundException is a checked exception that is thrown when we attempt to access a non-existing file.
3. InterruptedException: InterruptedException is a checked exception that is thrown when a thread is in sleeping or waiting state and another thread attempt to interrupt it.
4. InstantiationException: This exception is also a checked exception that is thrown when we try to create an object of abstract class or interface. That is, an InstantiationException exception occurs when an abstract class or interface is instantiated.
5. IllegalAccessException: The IllegalAccessException is a checked exception and it is thrown when a method is called in another method or class but the calling method or class does not have permission to access that method.
6. CloneNotSupportedException: This checked exception is thrown when we try to clone an object without implementing the cloneable interface.
7. NoSuchFieldException: This is a checked exception that is thrown when an unknown variable is used in a program.
8. NoSuchMethodException: This checked exception is thrown when the undefined method is used in a program.
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.
Let’s see a brief description of them.
1. ArithmeticException: This exception is thrown when arithmetic problems, such as a number is divided by zero, is occurred. That is, it is caused by maths error.
2. ClassCastException: The ClassCastException is a runtime exception that is thrown by JVM when we attempt to invalid typecasting in the program. That is, it is thrown when we cast an object to a subclass of which an object is not an instance.
3. IllegalArgumentException: This runtime exception is thrown by programmatically when an illegal or appropriate argument is passed to call a method. This exception class has further two subclasses:
● Number Format Exception
● Illegal Thread State Exception
Numeric Format Exception: Number Format Exception is thrown by programmatically when we try to convert a string into the numeric type and the process of illegal conversion fails. That is, it occurs due to the illegal conversion of a string to a numeric format.
Illegal Thread State Exception: Illegal Thread State Exception is a runtime exception that is thrown by programmatically when we attempt to perform any operation on a thread but it is incompatible with the current thread state.
4. IndexOutOfBoundsException: This exception class is thrown by JVM when an array or string is going out of the specified index. It has two further subclasses:
● ArrayIndexOutOfBoundsException
● StringIndexOutOfBoundsException
ArrayIndexOutOfBoundsException: ArrayIndexOutOfBoundsException exception is thrown when an array element is accessed out of the index.
StringIndexOutOfBoundsException: StringIndexOutOfBoundsException exception is thrown when a String or StringBuffer element is accessed out of the index.
5. Null Pointer Exception: Null Pointer Exception is a runtime exception that is thrown by JVM when we attempt to use null instead of an object. That is, it is thrown when the reference is null.
6. Array Store Exception: This exception occurs when we attempt to store any value in an array which is not of array type. For example, suppose, an array is of integer type but we are trying to store a value of an element of another type.
7. IllegalStateException: The IllegalStateException exception is thrown by programmatically when the runtime environment is not in an appropriate state for calling any method.
8. IllegalMonitorStateException: This exception is thrown when a thread does not have the right to monitor an object and tries to access wait(), notify(), and notifyAll() methods of the object.
9. NegativeArraySizeException: The NegativeArraySizeException exception is thrown when an array is created with a negative size.
3) Error
Error is irrecoverable. Some examples of errors are Out Of Memory Error, Virtual Machine Error, Assertion Error etc.
Difference between Checked and Unchecked Exceptions
Checked Exception | Unchecked Exception |
These exceptions are checked at compile time. These exceptions are handled at compile time too. | These exceptions are just opposite to the checked exceptions. These exceptions are not checked and handled at compile time. |
These exceptions are direct subclasses of exception but not extended from RuntimeException class. | They are the direct subclasses of the RuntimeException class. |
The code gives a compilation error in the case when a method throws a checked exception. The compiler is not able to handle the exception on its own. | The code compiles without any error because the exceptions escape the notice of the compiler. These exceptions are the results of user-created errors in programming logic. |
These exceptions mostly occur when the probability of failure is too high. | These exceptions occur mostly due to programming mistakes. |
Common checked exceptions include IOException, DataAccessException, InterruptedException, etc. | Common unchecked exceptions include ArithmeticException, InvalidClassException, NullPointerException, etc. |
These exceptions are propagated using the throws keyword. | These are automatically propagated. |
It is required to provide the try-catch and try-finally block to handle the checked exception. | In the case of unchecked exception it is not mandatory. |
Key takeaway
The classes that directly inherit the Throwable class except RuntimeException and Error are known as checked exceptions.
The classes that inherit the RuntimeException are known as unchecked exceptions.
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 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 of try block, the rest of the block code will not execute. So, it is recommended not to keeping 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.
Problem without exception handling
Let's try to understand the problem if we don't use a try-catch block.
Example 1
- 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 can be 100 lines of code after exception. So all the code after exception will not be executed.
Solution by exception handling
Let's see the solution of the above problem by a java try-catch block.
Example 2
- 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
Now, as displayed in the above example, the rest of the code is executed, i.e., the rest of the code statement is printed.
Example 3
In this example, we also kept the code in a try block that will not throw an exception.
- Public class TryCatchExample3 {
- Public static void main(String[] args) {
- Try
- {
- Int data=50/0; //may throw exception
- // if exception occurs, the remaining statement will not exceute
- System.out.println("rest of the code");
- }
- // handling the exception
- Catch(ArithmeticException e)
- {
- System.out.println(e);
- }
- }
- }
Output:
Java.lang.ArithmeticException: / by zero
Here, we can see that if an exception occurs in the try block, the rest of the block code will not execute.
Example 4
Here, we handle the exception using the parent class exception.
- Public class TryCatchExample4 {
- Public static void main(String[] args) {
- Try
- {
- Int data=50/0; //may throw exception
- }
- // handling the exception by using Exception class
- Catch(Exception e)
- {
- System.out.println(e);
- }
- System.out.println("rest of the code");
- }
- }
Output:
Java.lang.ArithmeticException: / by zero
Rest of the code
Fig 5 -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:
● Prints out exception description.
● Prints the stack trace (Hierarchy of methods where the exception occurred).
● Causes the program to terminate.
But if exception is handled by the application programmer, normal flow of the application is maintained i.e. rest of the code is executed.
Java catch multiple exceptions
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.
Example 1
Let's see a simple example of java multi-catch block.
- 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
Rest of the code
Example 2
- Public class MultipleCatchBlock2 {
- Public static void main(String[] args) {
- Try{
- Int a[]=new int[5];
- System.out.println(a[10]);
- }
- 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:
ArrayIndexOutOfBounds Exception occurs
Rest of the code
Example 3
In this example, try block contains two exceptions. But at a time only one exception occurs and its corresponding catch block is invoked.
- Public class MultipleCatchBlock3 {
- Public static void main(String[] args) {
- Try{
- Int a[]=new int[5];
- a[5]=30/0;
- System.out.println(a[10]);
- }
- 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
Rest of the code
Java Nested try block
The try block within a try block is known as nested try block in java.
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:
- ....
- Try
- {
- Statement 1;
- Statement 2;
- Try
- {
- Statement 1;
- Statement 2;
- }
- Catch(Exception e)
- {
- }
- }
- Catch(Exception e)
- {
- }
- ....
Java nested try example
Let's see a simple example of java nested try block.
- Class Excep6{
- Public static void main(String args[]){
- Try{
- Try{
- System.out.println("going to divide");
- Int b =39/0;
- }catch(ArithmeticException e){System.out.println(e);}
- Try{
- Int a[]=new int[5];
- a[5]=4;
- }catch(ArrayIndexOutOfBoundsException e){System.out.println(e);}
- System.out.println("other statement);
- }catch(Exception e){System.out.println("handled");}
- System.out.println("normal flow..");
- }
- }
Java finally block
Java finally block is a block that is used to execute important code such as closing connection, stream etc.
Java finally block is always executed whether exception is handled or not.
Fig 6 - Java finally block follows try or catch block.
Note: If you don't handle exception, before terminating the program, JVM executes finally block(if any).
Why use java finally
● Finally block in java can be used to put "cleanup" code such as closing a file, closing connection etc.
Usage of Java finally
Let's see the different cases where java finally block can be used.
Case 1
Let's see the java finally example where exception doesn't occur.
- Class TestFinallyBlock{
- Public static void main(String args[]){
- Try{
- Int data=25/5;
- System.out.println(data);
- }
- Catch(NullPointerException e){System.out.println(e);}
- Finally{System.out.println("finally block is always executed");}
- System.out.println("rest of the code...");
- }
- }
Output:5
Finally block is always executed
Rest of the code...
Case 2
Let's see the java finally example where exception occurs and not handled.
- Class TestFinallyBlock1{
- Public static void main(String args[]){
- Try{
- Int data=25/0;
- System.out.println(data);
- }
- Catch(NullPointerException e){System.out.println(e);}
- Finally{System.out.println("finally block is always executed");}
- System.out.println("rest of the code...");
- }
- }
Output:finally block is always executed
Exception in thread main java.lang.ArithmeticException:/ by zero
Java throw exception
Java throw keyword
The Java throw keyword is used to explicitly throw an exception.
We can throw either checked or unchecked exception in java by throw keyword. The throw keyword is mainly used to throw custom exception. We will see custom exceptions later.
The syntax of java throw keyword is given below.
- Throw exception;
Let's see the example of throw IOException.
- Throw new IOException("sorry device error);
Java throw keyword example
In this example, we have created the validate method that takes integer value as a parameter. If the age is less than 18, we are throwing the ArithmeticException otherwise print a message welcome to vote.
- Public class TestThrow1{
- Static void validate(int age){
- If(age<18)
- Throw new ArithmeticException("not valid");
- Else
- System.out.println("welcome to vote");
- }
- Public static void main(String args[]){
- Validate(13);
- System.out.println("rest of the code...");
- }
- }
Output:
Exception in thread main java.lang.ArithmeticException:not valid
Java throws keyword
The Java throws keyword is used to declare an exception. It gives information to the programmer that there may occur an exception so it is better for the programmer to provide the exception handling code so that normal flow can be maintained.
Exception Handling is mainly used to handle the checked exceptions. If there occurs any unchecked exception such as NullPointerException, it is programmers fault that he is not performing check up before the code being used.
Syntax of java throws
- Return_type method_name() throws exception_class_name{
- //method code
- }
Advantage of Java throws keyword
Now Checked Exception can be propagated (forwarded in call stack).
It provides information to the caller of the method about the exception.
Java throws example
Let's see the example of java throws clause which describes that checked exceptions can be propagated by throws keyword.
- Import java.io.IOException;
- Class Testthrows1{
- Void m()throws IOException{
- Throw new IOException("device error");//checked exception
- }
- Void n()throws IOException{
- m();
- }
- Void p(){
- Try{
- n();
- }catch(Exception e){System.out.println("exception handled");}
- }
- Public static void main(String args[]){
- Testthrows1 obj=new Testthrows1();
- Obj.p();
- System.out.println("normal flow...");
- }
- }
Output:
Exception handled
Normal flow...
Rule: If you are calling a method that declares an exception, you must either caught or declare the exception.
There are two cases:
- Case1: You caught the exception i.e. handle the exception using try/catch.
- Case2: You declare the exception i.e. specifying throws with the method.
Case1: You handle the exception
● In case you handle the exception, the code will be executed fine whether exception occurs during the program or not.
- Import java.io.*;
- Class M{
- Void method()throws IOException{
- Throw new IOException("device error");
- }
- }
- Public class Testthrows2{
- Public static void main(String args[]){
- Try{
- M m=new M();
- m.method();
- }catch(Exception e){System.out.println("exception handled");}
- System.out.println("normal flow...");
- }
- }
Output:
Exception handled
Normal flow…
Case2: You declare the exception
● In case you declare the exception, if exception does not occur, the code will be executed fine.
● B)In case you declare the exception if exception occurs, an exception will be thrown at runtime because throws does not handle the exception.
A) Program if exception does not occur
- Import java.io.*;
- Class M{
- Void method()throws IOException{
- System.out.println("device operation performed");
- }
- }
- Class Testthrows3{
- Public static void main(String args[])throws IOException{//declare exception
- M m=new M();
- m.method();
- System.out.println("normal flow...");
- }
- }
Output:
Device operation performed
Normal flow...
B) Program if exception occurs
- Import java.io.*;
- Class M{
- Void method()throws IOException{
- Throw new IOException("device error");
- }
- }
- Class Testthrows4{
- Public static void main(String args[])throws IOException{//declare exception
- M m=new M();
- m.method();
- System.out.println("normal flow...");
- }
- }
Output:
Runtime Exception
Difference between throw and throws in Java
There are many differences between throw and throws keywords. A list of differences between throw and throws are given below:
No. | Throw | Throws |
1) | Java throw keyword is used to explicitly throw an exception. | Java throws keyword is used to declare an exception. |
2) | Checked exception cannot be propagated using throw only. | Checked exception can be propagated with throws. |
3) | Throw is followed by an instance. | Throws is followed by class. |
4) | Throw is used within the method. | Throws is used with the method signature. |
5) | You cannot throw multiple exceptions. | You can declare multiple exceptions e.g. |
Java throw example
- Void m(){
- Throw new ArithmeticException("sorry");
- }
Java throws example
- Void m()throws ArithmeticException{
- //method code
- }
Java throw and throws example
- Void m()throws ArithmeticException{
- Throw new ArithmeticException("sorry");
- }
Difference between final, finally and finalize
There are many differences between final, finally and finalize. A list of differences between final, finally and finalize are given below:
Key | Final | Finally | Finalize |
Definition | Final is the keyword and access modifier which is used to apply restrictions on a class, method or variable. | Finally is the block in Java Exception Handling to execute the important code whether the exception occurs or not. | Finalize is the method in Java which is used to perform clean up processing just before object is garbage collected. |
Applicable to | Final keyword is used with the classes, methods and variables. | Finally block is always related to the try and catch block in exception handling. | Finalize() method is used with the objects. |
Functionality | (1) Once declared, final variable becomes constant and cannot be modified. (2) final method cannot be overridden by sub class. (3) final class cannot be inherited. | (1) finally block runs the important code even if exception occurs or not. (2) finally block cleans up all the resources used in try block | Finalize method performs the cleaning activities with respect to the object before its destruction. |
Execution | Final method is executed only when we call it. | Finally block is executed as soon as the try-catch block is executed. It's execution is not dependant on the exception. | Finalize method is executed just before the object is destroyed. |
Java final example
- Class FinalExample{
- Public static void main(String[] args){
- Final int x=100;
- x=200;//Compile Time Error
- }}
Java finally example
- Class FinallyExample{
- Public static void main(String[] args){
- Try{
- Int x=300;
- }catch(Exception e){System.out.println(e);}
- Finally{System.out.println("finally block is executed");}
- }}
Java finalize example
- Class FinalizeExample{
- Public void finalize(){System.out.println("finalize called");}
- Public static void main(String[] args){
- FinalizeExample f1=new FinalizeExample();
- FinalizeExample f2=new FinalizeExample();
- f1=null;
- f2=null;
- System.gc();
- }}
Key takeaway
Java try block is used to enclose the code that might throw an exception. It must be used within the method.
Java catch block is used to handle the Exception by declaring the type of exception within the parameter.
References:
1. T. Budd (2009), An Introduction to Object Oriented Programming, 3rd edition, Pearson Education, India.
2. J. Nino, F. A. Hosch (2002), An Introduction to programming and OO design using Java, John Wiley & sons, New Jersey.
3. Y. Daniel Liang (2010), Introduction to Java programming, 7th edition, Pearson education, India.
4. Object Oriented Programming with C++ by E Balagurusamy, Fifth Edition, TMH.
Unit - 5
Multithreading in java
Unit - 5
Multithreading in java
In Java, multithreading is the process of running several threads at the same time.
A thread is the smallest unit of processing and is a lightweight sub-process. Multitasking is accomplished through the use of multiprocessing and multithreading.
Because threads share memory, we employ multithreading rather than multiprocessing. They conserve memory by not allocating a separate memory space, and context-switching between threads takes less time than processing.
Multithreading in Java is typically utilized in gaming, animation, and other similar applications.
Because Java is a multi-threaded programming language, we can use it to create multi-threaded programs. A multi-threaded program is made up of two or more portions that can operate in parallel, each of which can tackle a distinct task at the same time, maximizing the use of available resources, especially when your computer has several CPUs.
Multitasking is defined as the sharing of common processing resources, such as a CPU, by many processes. Multi-threading extends the concept of multitasking into programs by allowing you to divide certain operations within a single app into several threads. Each thread can execute in its own thread. Not only does the operating system split processing time among distinct apps, but it also divides it among each thread within an application.
Multi-threading allows you to write software in which multiple activities can run at the same time.
The Java Thread Model
The Java run-time system depends on threads for many things, and all the class libraries are designed with multithreading in mind. In fact, Java uses threads to enable the entire environment to be asynchronous. This helps reduce inefficiency by preventing the waste of CPU cycles.
The value of a multithreaded environment is best understood in contrast to its counterpart. Single-threaded systems use an approach called an event loop with polling. In this model, a single thread of control runs in an infinite loop, polling a single event queue to decide what to do next. Once this polling mechanism returns with, say, a signal that a network file is ready to be read, then the event loop dispatches control to the appropriate event handler. Until this event handler returns, nothing else can happen in the program. This wastes CPU time. It can also result in one part of a program dominating the system and preventing any other events from being processed. In general, in a single-threaded environment, when a thread blocks (that is, suspends execution) because it is waiting for some resource, the entire program stops running.
The benefit of Java’s multithreading is that the main loop/polling mechanism is eliminated. One thread can pause without stopping other parts of your program. For example, the idle time created when a thread reads data from a network or waits for user input can be utilized elsewhere. Multithreading allows animation loops to sleep for a second between each frame without causing the whole system to pause. When a thread blocks in a Java program, only the single thread that is blocked pauses. All other threads continue to run.
As most readers know, over the past few years, multi-core systems have become commonplace. Of course, single-core systems are still in widespread use. It is important to understand that Java’s multithreading features work in both types of systems. In a single-core system, concurrently executing threads share the CPU, with each thread receiving a slice of CPU time. Therefore, in a single-core system, two or more threads do not actually run at the same time, but idle CPU time is utilized. However, in multi-core systems, it is possible for two or more threads to actually execute simultaneously. In many cases, this can further improve program efficiency and increase the speed of certain operations.
Threads exist in several states. Here is a general description. A thread can be running. It can be ready to run as soon as it gets CPU time. A running thread can be suspended, which temporarily halts its activity. A suspended thread can then be resumed, allowing it to pick up where it left off. A thread can be blocked when waiting for a resource. At any time, a thread can be terminated, which halts its execution immediately. Once terminated, a thread cannot be resumed.
Life Cycle of a Thread
A thread goes through various stages in its life cycle. For example, a thread is born, started, runs, and then dies. The following diagram shows the complete life cycle of a thread.
Fig 1 - The complete life cycle of a thread
Following are the stages of the life cycle −
● New − A new thread begins its life cycle in the new state. It remains in this state until the program starts the thread. It is also referred to as a born thread.
● Runnable − After a newly born thread is started, the thread becomes runnable. A thread in this state is considered to be executing its task.
● Waiting − Sometimes, a thread transitions to the waiting state while the thread waits for another thread to perform a task. A thread transitions back to the runnable state only when another thread signals the waiting thread to continue executing.
● Timed Waiting − A runnable thread can enter the timed waiting state for a specified interval of time. A thread in this state transitions back to the runnable state when that time interval expires or when the event it is waiting for occurs.
● Terminated (Dead) − A runnable thread enters the terminated state when it completes its task or otherwise terminates.
Thread Methods
Following is the list of important methods available in the Thread class.
Sr.No. | Method & Description |
1 | Public void start() Starts the thread in a separate path of execution, then invokes the run() method on this Thread object. |
2 | Public void run() If this Thread object was instantiated using a separate Runnable target, the run() method is invoked on that Runnable object. |
3 | Public final void setName(String name) Changes the name of the Thread object. There is also a getName() method for retrieving the name. |
4 | Public final void setPriority(int priority) Sets the priority of this Thread object. The possible values are between 1 and 10. |
5 | Public final void setDaemon(boolean on) A parameter of true denotes this Thread as a daemon thread. |
6 | Public final void join(long millisec) The current thread invokes this method on a second thread, causing the current thread to block until the second thread terminates or the specified number of milliseconds passes. |
7 | Public void interrupt() Interrupts this thread, causing it to continue execution if it was blocked for any reason. |
8 | Public final boolean isAlive() Returns true if the thread is alive, which is any time after the thread has been started but before it runs to completion. |
The previous methods are invoked on a particular Thread object. The following methods in the Thread class are static. Invoking one of the static methods performs the operation on the currently running thread.
Sr.No. | Method & Description |
1 | Public static void yield() Causes the currently running thread to yield to any other threads of the same priority that are waiting to be scheduled. |
2 | Public static void sleep(long millisec) Causes the currently running thread to block for at least the specified number of milliseconds. |
3 | Public static boolean holdsLock(Object x) Returns true if the current thread holds the lock on the given Object. |
4 | Public static Thread currentThread() Returns a reference to the currently running thread, which is the thread that invokes this method. |
5 | Public static void dumpStack() Prints the stack trace for the currently running thread, which is useful when debugging a multithreaded application. |
Example
The following ThreadClassDemo program demonstrates some of these methods of the Thread class. Consider a class DisplayMessage which implements Runnable −
// File Name : DisplayMessage.java
// Create a thread to implement Runnable
Public class DisplayMessage implements Runnable {
Private String message;
Public DisplayMessage(String message) {
This.message = message;
}
Public void run() {
While(true) {
System.out.println(message);
}
}
}
Following is another class which extends the Thread class −
// File Name : GuessANumber.java
// Create a thread to extend Thread
Public class GuessANumber extends Thread {
Private int number;
Public GuessANumber(int number) {
This.number = number;
}
Public void run() {
Int counter = 0;
Int guess = 0;
Do {
Guess = (int) (Math.random() * 100 + 1);
System.out.println(this.getName() + " guesses " + guess);
Counter++;
} while(guess != number);
System.out.println("** Correct!" + this.getName() + "in" + counter + "guesses.**");
}
}
Following is the main program, which makes use of the above-defined classes −
// File Name : ThreadClassDemo.java
Public class ThreadClassDemo {
Public static void main(String [] args) {
Runnable hello = new DisplayMessage("Hello");
Thread thread1 = new Thread(hello);
Thread1.setDaemon(true);
Thread1.setName("hello");
System.out.println("Starting hello thread...");
Thread1.start();
Runnable bye = new DisplayMessage("Goodbye");
Thread thread2 = new Thread(bye);
Thread2.setPriority(Thread.MIN_PRIORITY);
Thread2.setDaemon(true);
System.out.println("Starting goodbye thread...");
Thread2.start();
System.out.println("Starting thread3...");
Thread thread3 = new GuessANumber(27);
Thread3.start();
Try {
Thread3.join();
} catch (InterruptedException e) {
System.out.println("Thread interrupted.");
}
System.out.println("Starting thread4...");
Thread thread4 = new GuessANumber(75);
Thread4.start();
System.out.println("main() is ending...");
}
}
This will produce the following result. You can try this example again and again and you will get a different result every time.
Output
Starting hello thread...
Starting goodbye thread...
Hello
Hello
Hello
Hello
Hello
Hello
Goodbye
Goodbye
Goodbye
Goodbye
Goodbye
.......
Key takeaway
Multithreading is the process of running several threads at the same time.
Multithreading in Java is typically utilized in gaming, animation, and other similar applications.
A thread goes through various stages in its life cycle. For example, a thread is born, started, runs, and then dies. The following diagram shows the complete life cycle of a thread.
Java.lang. Runnable is an interface that a class must implement if its instances are to be executed by a thread. Subclass Thread and implement Runnable are two techniques to start a new Thread. When a task can be accomplished by overriding simply the run() function of Runnable, there is no need to subclass Thread.
Steps to create a new Thread using Runnable
● Make a Runnable implementer and use it to call the run() method.
● Create a Thread object and pass the implementer to it; Thread has a function Object() { [native code] } that takes Runnable objects.
● Invoke the Thread instance's start() method, which runs the implementer's run() method inside. When you call start(), it generates a new Thread that runs the code you wrote in run ().
When you call run() directly, it does not create and start a new Thread; instead, it continues to execute in the same thread. To start a new line of execution, call start() on the thread.
Example
Public class RunnableDemo {
Public static void main(String[] args)
{
System.out.println("Main thread is- "
+ Thread.currentThread().getName());
Thread t1 = new Thread(new RunnableDemo().new RunnableImpl());
t1.start();
}
Private class RunnableImpl implements Runnable {
Public void run()
{
System.out.println(Thread.currentThread().getName()
+ ", executing run() method!");
}
}
}
Output
Main thread is- main
Thread-0, executing run() method!
The main thread executes the main method, while executing start on RunnableImpl produces and starts a new thread, Thread-0.
The Thread Class and the Runnable Interface
Java’s multithreading system is built upon the Thread class, its methods, and its companion interface, Runnable. Thread encapsulates a thread of execution. Since you can’t directly refer to the ethereal state of a running thread, you will deal with it through its proxy, the Thread instance that spawned it. To create a new thread, your program will either extend Thread or implement the Runnable interface.
The Thread class defines several methods that help manage threads. Several of those used is shown here:
Fig 2 - Thread class defines several methods
Thus far, all the examples in this book have used a single thread of execution. The remainder of this chapter explains how to use Thread and Runnable to create and manage threads, beginning with the one thread that all Java programs have: the main thread.
Create a Thread by Implementing a Runnable Interface
If your class is intended to be executed as a thread then you can achieve this by implementing a Runnable interface. You will need to follow three basic steps −
Step 1
As a first step, you need to implement a run() method provided by a Runnable interface. This method provides an entry point for the thread and you will put your complete business logic inside this method. Following is a simple syntax of the run() method −
Public void run( )
Step 2
As a second step, you will instantiate a Thread object using the following constructor −
Thread(Runnable threadObj, String threadName);
Where, threadObj is an instance of a class that implements the Runnable interface and threadName is the name given to the new thread.
Step 3
Once a Thread object is created, you can start it by calling start() method, which executes a call to run( ) method. Following is a simple syntax of start() method −
Void start();
Example
Here is an example that creates a new thread and starts running it −
Class RunnableDemo implements Runnable {
Private Thread t;
Private String threadName;
RunnableDemo( String name) {
ThreadName = name;
System.out.println("Creating " + threadName );
}
Public void run() {
System.out.println("Running " + threadName );
Try {
For(int i = 4; i > 0; i--) {
System.out.println("Thread: " + threadName + ", " + i);
// Let the thread sleep for a while.
Thread.sleep(50);
}
} catch (InterruptedException e) {
System.out.println("Thread " + threadName + " interrupted.");
}
System.out.println("Thread " + threadName + " exiting.");
}
Public void start () {
System.out.println("Starting " + threadName );
If (t == null) {
t = new Thread (this, threadName);
t.start ();
}
}
}
Public class TestThread {
Public static void main(String args[]) {
RunnableDemo R1 = new RunnableDemo( "Thread-1");
R1.start();
RunnableDemo R2 = new RunnableDemo( "Thread-2");
R2.start();
}
}
This will produce the following result −
Output
Creating Thread-1
Starting Thread-1
Creating Thread-2
Starting Thread-2
Running Thread-1
Thread: Thread-1, 4
Running Thread-2
Thread: Thread-2, 4
Thread: Thread-1, 3
Thread: Thread-2, 3
Thread: Thread-1, 2
Thread: Thread-2, 2
Thread: Thread-1, 1
Thread: Thread-2, 1
Thread Thread-1 exiting.
Thread Thread-2 exiting.
Key takeaway
Java.lang. Runnable is an interface that a class must implement if its instances are to be executed by a thread. Subclass Thread and implement Runnable are two techniques to start a new Thread.
Synchronization in java is the capability to control the access of multiple threads to any shared resource.
Java Synchronization is better option where we want to allow only one thread to access the shared resource.
When we start two or more threads in a program, it's possible that numerous threads will try to access the same resource, resulting in unexpected results due to concurrency difficulties. For example, if multiple threads try to write to the same file at the same time, the data may be corrupted because one of the threads can override data, or while one thread is opening and another is closing the same file.
As a result, it's necessary to synchronize many threads' actions and ensure that only one thread can access the resource at any given time. This is accomplished through the use of monitors. In Java, each object has its own monitor, which a thread can lock or unlock. On a display, only one thread can retain a lock at a time.
Using synchronized blocks, the Java programming language makes it relatively easy to create threads and synchronize their tasks. Within this block, you retain shared resources. The general form of the synchronized statement is as follows:
Syntax
Synchronized(objectidentifier)
{
// Access shared variables and other shared resources
}
The objec tidentifier is a reference to an object whose lock corresponds to the monitor represented by the synchronized statement. Now we'll look at two different ways to print a counter using two distinct threads. When threads are not synchronized, they publish counter values that are out of order, but when we print counter inside a synchronized() block, it prints counters that are very much in order for both threads.
Multithreading Example with synchronization
Class PrintDemo {
Public void printCount() {
Try {
For(int i = 5; i > 0; i--) {
System.out.println("Counter --- " + i );
}
} catch (Exception e) {
System.out.println("Thread interrupted.");
}
}
}
Class ThreadDemo extends Thread {
Private Thread t;
Private String threadName;
PrintDemo PD;
ThreadDemo( String name, PrintDemo pd) {
ThreadName = name;
PD = pd;
}
Public void run() {
Synchronized(PD) {
PD.printCount();
}
System.out.println("Thread " + threadName + " exiting.");
}
Public void start () {
System.out.println("Starting " + threadName );
If (t == null) {
t = new Thread (this, threadName);
t.start ();
}
}
}
Public class TestThread {
Public static void main(String args[]) {
PrintDemo PD = new PrintDemo();
ThreadDemo T1 = new ThreadDemo( "Thread - 1 ", PD );
ThreadDemo T2 = new ThreadDemo( "Thread - 2 ", PD );
T1.start();
T2.start();
// wait for threads to end
Try {
T1.join();
T2.join();
} catch ( Exception e) {
System.out.println("Interrupted");
}
}
}
Output
Starting Thread - 1
Starting Thread - 2
Counter --- 5
Counter --- 4
Counter --- 3
Counter --- 2
Counter --- 1
Thread Thread - 1 exiting.
Counter --- 5
Counter --- 4
Counter --- 3
Counter --- 2
Counter --- 1
Thread Thread - 2 exiting.
Why use Synchronization
The synchronization is mainly used to
- To prevent thread interference.
- To prevent consistency problem.
Types of Synchronization
There are two types of synchronization
- Process Synchronization
- Thread Synchronization
Understanding the problem without Synchronization
In this example, there is no synchronization, so output is inconsistent. Let's see the example:
- Class Table{
- Void printTable(int n){//method not synchronized
- For(int i=1;i<=5;i++){
- System.out.println(n*i);
- Try{
- Thread.sleep(400);
- }catch(Exception e){System.out.println(e);}
- }
- }
- }
- Class MyThread1 extends Thread{
- Table t;
- MyThread1(Table t){
- This.t=t;
- }
- Public void run(){
- t.printTable(5);
- }
- }
- Class MyThread2 extends Thread{
- Table t;
- MyThread2(Table t){
- This.t=t;
- }
- Public void run(){
- t.printTable(100);
- }
- }
- Class TestSynchronization1{
- Public static void main(String args[]){
- Table obj = new Table();//only one object
- MyThread1 t1=new MyThread1(obj);
- MyThread2 t2=new MyThread2(obj);
- t1.start();
- t2.start();
- }
- }
Output: 5
100
10
200
15
300
20
400
25
500
Java synchronized method
If you declare any method as synchronized, it is known as synchronized method.
Synchronized method is used to lock an object for any shared resource.
When a thread invokes a synchronized method, it automatically acquires the lock for that object and releases it when the thread completes its task.
Key takeaway
Using synchronized blocks, the Java programming language makes it relatively easy to create threads and synchronize their tasks. Within this block, you retain shared resources.
● The Exception Handling in Java is one of the powerful mechanisms to handle the runtime errors so that the normal flow of the application can be maintained.
● 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 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.
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 use exception handling. Let's take 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 your program and there occurs an exception at statement 5, the rest of the code will not be executed i.e. statement 6 to 10 will not be executed. If we perform exception handling, the rest of the statement will be executed. That is why we use exception handling in Java.
Benefits of exception handling
● When an exception occurs, exception handling guarantees that the program's flow is preserved.
● This allows us to identify the different types of faults.
● This allows us to develop error-handling code separately from the rest of the code.
When an exception occurs, exception handling ensures that the program's flow does not break. For example, if a programme has a large number of statements and an exception occurs in the middle of executing some of them, the statements after the exception will not be executed, and the programme will end abruptly.
By handling, we ensure that all of the statements are executed and that the program's flow is not disrupted.
Key takeaway
The Exception Handling in Java is one of the powerful mechanisms to handle the runtime errors so that the normal flow of the application can be maintained.
Hierarchy of Java Exception classes
The java.lang.Throwable class is the root class of Java Exception hierarchy which is inherited by two subclasses: Exception and Error.
All exception and error kinds are subclasses of the hierarchy's root class, Throwable. Exception is in charge of one branch. This class is used for unusual circumstances that user programmes should be aware of. An example of such an exception is the NullPointerException. The Java run-time system (JVM) uses another branch, Error, to identify issues related to the run-time environment (JRE). An example of such an error is StackOverflowError.
A hierarchy of Java Exception classes are given below:
Fig 3 - A hierarchy of Java Exception classes
Types of Java Exceptions
There are mainly two types of exceptions: checked and unchecked. Here, an error is considered as the unchecked exception. According to Oracle, there are three types of exceptions:
- Checked Exception
- Unchecked Exception
- Error
Fig 4 – Exception handling
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:
❖ The classes that directly inherit the Throwable class except RuntimeException and Error are known as checked exceptions.
❖ For example, IOException, SQLException, etc. Checked exceptions are checked at compile-time.
1. ClassNotFoundException: The ClassNotFoundException is a kind of checked exception that is thrown when we attempt to use a class that does not exist.
Checked exceptions are those exceptions that are checked by the Java compiler itself.
2. FileNotFoundException: The FileNotFoundException is a checked exception that is thrown when we attempt to access a non-existing file.
3. InterruptedException: InterruptedException is a checked exception that is thrown when a thread is in sleeping or waiting state and another thread attempt to interrupt it.
4. InstantiationException: This exception is also a checked exception that is thrown when we try to create an object of abstract class or interface. That is, an InstantiationException exception occurs when an abstract class or interface is instantiated.
5. IllegalAccessException: The IllegalAccessException is a checked exception and it is thrown when a method is called in another method or class but the calling method or class does not have permission to access that method.
6. CloneNotSupportedException: This checked exception is thrown when we try to clone an object without implementing the cloneable interface.
7. NoSuchFieldException: This is a checked exception that is thrown when an unknown variable is used in a program.
8. NoSuchMethodException: This checked exception is thrown when the undefined method is used in a program.
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.
Let’s see a brief description of them.
1. ArithmeticException: This exception is thrown when arithmetic problems, such as a number is divided by zero, is occurred. That is, it is caused by maths error.
2. ClassCastException: The ClassCastException is a runtime exception that is thrown by JVM when we attempt to invalid typecasting in the program. That is, it is thrown when we cast an object to a subclass of which an object is not an instance.
3. IllegalArgumentException: This runtime exception is thrown by programmatically when an illegal or appropriate argument is passed to call a method. This exception class has further two subclasses:
● Number Format Exception
● Illegal Thread State Exception
Numeric Format Exception: Number Format Exception is thrown by programmatically when we try to convert a string into the numeric type and the process of illegal conversion fails. That is, it occurs due to the illegal conversion of a string to a numeric format.
Illegal Thread State Exception: Illegal Thread State Exception is a runtime exception that is thrown by programmatically when we attempt to perform any operation on a thread but it is incompatible with the current thread state.
4. IndexOutOfBoundsException: This exception class is thrown by JVM when an array or string is going out of the specified index. It has two further subclasses:
● ArrayIndexOutOfBoundsException
● StringIndexOutOfBoundsException
ArrayIndexOutOfBoundsException: ArrayIndexOutOfBoundsException exception is thrown when an array element is accessed out of the index.
StringIndexOutOfBoundsException: StringIndexOutOfBoundsException exception is thrown when a String or StringBuffer element is accessed out of the index.
5. Null Pointer Exception: Null Pointer Exception is a runtime exception that is thrown by JVM when we attempt to use null instead of an object. That is, it is thrown when the reference is null.
6. Array Store Exception: This exception occurs when we attempt to store any value in an array which is not of array type. For example, suppose, an array is of integer type but we are trying to store a value of an element of another type.
7. IllegalStateException: The IllegalStateException exception is thrown by programmatically when the runtime environment is not in an appropriate state for calling any method.
8. IllegalMonitorStateException: This exception is thrown when a thread does not have the right to monitor an object and tries to access wait(), notify(), and notifyAll() methods of the object.
9. NegativeArraySizeException: The NegativeArraySizeException exception is thrown when an array is created with a negative size.
3) Error
Error is irrecoverable. Some examples of errors are Out Of Memory Error, Virtual Machine Error, Assertion Error etc.
Difference between Checked and Unchecked Exceptions
Checked Exception | Unchecked Exception |
These exceptions are checked at compile time. These exceptions are handled at compile time too. | These exceptions are just opposite to the checked exceptions. These exceptions are not checked and handled at compile time. |
These exceptions are direct subclasses of exception but not extended from RuntimeException class. | They are the direct subclasses of the RuntimeException class. |
The code gives a compilation error in the case when a method throws a checked exception. The compiler is not able to handle the exception on its own. | The code compiles without any error because the exceptions escape the notice of the compiler. These exceptions are the results of user-created errors in programming logic. |
These exceptions mostly occur when the probability of failure is too high. | These exceptions occur mostly due to programming mistakes. |
Common checked exceptions include IOException, DataAccessException, InterruptedException, etc. | Common unchecked exceptions include ArithmeticException, InvalidClassException, NullPointerException, etc. |
These exceptions are propagated using the throws keyword. | These are automatically propagated. |
It is required to provide the try-catch and try-finally block to handle the checked exception. | In the case of unchecked exception it is not mandatory. |
Key takeaway
The classes that directly inherit the Throwable class except RuntimeException and Error are known as checked exceptions.
The classes that inherit the RuntimeException are known as unchecked exceptions.
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 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 of try block, the rest of the block code will not execute. So, it is recommended not to keeping 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.
Problem without exception handling
Let's try to understand the problem if we don't use a try-catch block.
Example 1
- 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 can be 100 lines of code after exception. So all the code after exception will not be executed.
Solution by exception handling
Let's see the solution of the above problem by a java try-catch block.
Example 2
- 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
Now, as displayed in the above example, the rest of the code is executed, i.e., the rest of the code statement is printed.
Example 3
In this example, we also kept the code in a try block that will not throw an exception.
- Public class TryCatchExample3 {
- Public static void main(String[] args) {
- Try
- {
- Int data=50/0; //may throw exception
- // if exception occurs, the remaining statement will not exceute
- System.out.println("rest of the code");
- }
- // handling the exception
- Catch(ArithmeticException e)
- {
- System.out.println(e);
- }
- }
- }
Output:
Java.lang.ArithmeticException: / by zero
Here, we can see that if an exception occurs in the try block, the rest of the block code will not execute.
Example 4
Here, we handle the exception using the parent class exception.
- Public class TryCatchExample4 {
- Public static void main(String[] args) {
- Try
- {
- Int data=50/0; //may throw exception
- }
- // handling the exception by using Exception class
- Catch(Exception e)
- {
- System.out.println(e);
- }
- System.out.println("rest of the code");
- }
- }
Output:
Java.lang.ArithmeticException: / by zero
Rest of the code
Fig 5 -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:
● Prints out exception description.
● Prints the stack trace (Hierarchy of methods where the exception occurred).
● Causes the program to terminate.
But if exception is handled by the application programmer, normal flow of the application is maintained i.e. rest of the code is executed.
Java catch multiple exceptions
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.
Example 1
Let's see a simple example of java multi-catch block.
- 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
Rest of the code
Example 2
- Public class MultipleCatchBlock2 {
- Public static void main(String[] args) {
- Try{
- Int a[]=new int[5];
- System.out.println(a[10]);
- }
- 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:
ArrayIndexOutOfBounds Exception occurs
Rest of the code
Example 3
In this example, try block contains two exceptions. But at a time only one exception occurs and its corresponding catch block is invoked.
- Public class MultipleCatchBlock3 {
- Public static void main(String[] args) {
- Try{
- Int a[]=new int[5];
- a[5]=30/0;
- System.out.println(a[10]);
- }
- 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
Rest of the code
Java Nested try block
The try block within a try block is known as nested try block in java.
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:
- ....
- Try
- {
- Statement 1;
- Statement 2;
- Try
- {
- Statement 1;
- Statement 2;
- }
- Catch(Exception e)
- {
- }
- }
- Catch(Exception e)
- {
- }
- ....
Java nested try example
Let's see a simple example of java nested try block.
- Class Excep6{
- Public static void main(String args[]){
- Try{
- Try{
- System.out.println("going to divide");
- Int b =39/0;
- }catch(ArithmeticException e){System.out.println(e);}
- Try{
- Int a[]=new int[5];
- a[5]=4;
- }catch(ArrayIndexOutOfBoundsException e){System.out.println(e);}
- System.out.println("other statement);
- }catch(Exception e){System.out.println("handled");}
- System.out.println("normal flow..");
- }
- }
Java finally block
Java finally block is a block that is used to execute important code such as closing connection, stream etc.
Java finally block is always executed whether exception is handled or not.
Fig 6 - Java finally block follows try or catch block.
Note: If you don't handle exception, before terminating the program, JVM executes finally block(if any).
Why use java finally
● Finally block in java can be used to put "cleanup" code such as closing a file, closing connection etc.
Usage of Java finally
Let's see the different cases where java finally block can be used.
Case 1
Let's see the java finally example where exception doesn't occur.
- Class TestFinallyBlock{
- Public static void main(String args[]){
- Try{
- Int data=25/5;
- System.out.println(data);
- }
- Catch(NullPointerException e){System.out.println(e);}
- Finally{System.out.println("finally block is always executed");}
- System.out.println("rest of the code...");
- }
- }
Output:5
Finally block is always executed
Rest of the code...
Case 2
Let's see the java finally example where exception occurs and not handled.
- Class TestFinallyBlock1{
- Public static void main(String args[]){
- Try{
- Int data=25/0;
- System.out.println(data);
- }
- Catch(NullPointerException e){System.out.println(e);}
- Finally{System.out.println("finally block is always executed");}
- System.out.println("rest of the code...");
- }
- }
Output:finally block is always executed
Exception in thread main java.lang.ArithmeticException:/ by zero
Java throw exception
Java throw keyword
The Java throw keyword is used to explicitly throw an exception.
We can throw either checked or unchecked exception in java by throw keyword. The throw keyword is mainly used to throw custom exception. We will see custom exceptions later.
The syntax of java throw keyword is given below.
- Throw exception;
Let's see the example of throw IOException.
- Throw new IOException("sorry device error);
Java throw keyword example
In this example, we have created the validate method that takes integer value as a parameter. If the age is less than 18, we are throwing the ArithmeticException otherwise print a message welcome to vote.
- Public class TestThrow1{
- Static void validate(int age){
- If(age<18)
- Throw new ArithmeticException("not valid");
- Else
- System.out.println("welcome to vote");
- }
- Public static void main(String args[]){
- Validate(13);
- System.out.println("rest of the code...");
- }
- }
Output:
Exception in thread main java.lang.ArithmeticException:not valid
Java throws keyword
The Java throws keyword is used to declare an exception. It gives information to the programmer that there may occur an exception so it is better for the programmer to provide the exception handling code so that normal flow can be maintained.
Exception Handling is mainly used to handle the checked exceptions. If there occurs any unchecked exception such as NullPointerException, it is programmers fault that he is not performing check up before the code being used.
Syntax of java throws
- Return_type method_name() throws exception_class_name{
- //method code
- }
Advantage of Java throws keyword
Now Checked Exception can be propagated (forwarded in call stack).
It provides information to the caller of the method about the exception.
Java throws example
Let's see the example of java throws clause which describes that checked exceptions can be propagated by throws keyword.
- Import java.io.IOException;
- Class Testthrows1{
- Void m()throws IOException{
- Throw new IOException("device error");//checked exception
- }
- Void n()throws IOException{
- m();
- }
- Void p(){
- Try{
- n();
- }catch(Exception e){System.out.println("exception handled");}
- }
- Public static void main(String args[]){
- Testthrows1 obj=new Testthrows1();
- Obj.p();
- System.out.println("normal flow...");
- }
- }
Output:
Exception handled
Normal flow...
Rule: If you are calling a method that declares an exception, you must either caught or declare the exception.
There are two cases:
- Case1: You caught the exception i.e. handle the exception using try/catch.
- Case2: You declare the exception i.e. specifying throws with the method.
Case1: You handle the exception
● In case you handle the exception, the code will be executed fine whether exception occurs during the program or not.
- Import java.io.*;
- Class M{
- Void method()throws IOException{
- Throw new IOException("device error");
- }
- }
- Public class Testthrows2{
- Public static void main(String args[]){
- Try{
- M m=new M();
- m.method();
- }catch(Exception e){System.out.println("exception handled");}
- System.out.println("normal flow...");
- }
- }
Output:
Exception handled
Normal flow…
Case2: You declare the exception
● In case you declare the exception, if exception does not occur, the code will be executed fine.
● B)In case you declare the exception if exception occurs, an exception will be thrown at runtime because throws does not handle the exception.
A) Program if exception does not occur
- Import java.io.*;
- Class M{
- Void method()throws IOException{
- System.out.println("device operation performed");
- }
- }
- Class Testthrows3{
- Public static void main(String args[])throws IOException{//declare exception
- M m=new M();
- m.method();
- System.out.println("normal flow...");
- }
- }
Output:
Device operation performed
Normal flow...
B) Program if exception occurs
- Import java.io.*;
- Class M{
- Void method()throws IOException{
- Throw new IOException("device error");
- }
- }
- Class Testthrows4{
- Public static void main(String args[])throws IOException{//declare exception
- M m=new M();
- m.method();
- System.out.println("normal flow...");
- }
- }
Output:
Runtime Exception
Difference between throw and throws in Java
There are many differences between throw and throws keywords. A list of differences between throw and throws are given below:
No. | Throw | Throws |
1) | Java throw keyword is used to explicitly throw an exception. | Java throws keyword is used to declare an exception. |
2) | Checked exception cannot be propagated using throw only. | Checked exception can be propagated with throws. |
3) | Throw is followed by an instance. | Throws is followed by class. |
4) | Throw is used within the method. | Throws is used with the method signature. |
5) | You cannot throw multiple exceptions. | You can declare multiple exceptions e.g. |
Java throw example
- Void m(){
- Throw new ArithmeticException("sorry");
- }
Java throws example
- Void m()throws ArithmeticException{
- //method code
- }
Java throw and throws example
- Void m()throws ArithmeticException{
- Throw new ArithmeticException("sorry");
- }
Difference between final, finally and finalize
There are many differences between final, finally and finalize. A list of differences between final, finally and finalize are given below:
Key | Final | Finally | Finalize |
Definition | Final is the keyword and access modifier which is used to apply restrictions on a class, method or variable. | Finally is the block in Java Exception Handling to execute the important code whether the exception occurs or not. | Finalize is the method in Java which is used to perform clean up processing just before object is garbage collected. |
Applicable to | Final keyword is used with the classes, methods and variables. | Finally block is always related to the try and catch block in exception handling. | Finalize() method is used with the objects. |
Functionality | (1) Once declared, final variable becomes constant and cannot be modified. (2) final method cannot be overridden by sub class. (3) final class cannot be inherited. | (1) finally block runs the important code even if exception occurs or not. (2) finally block cleans up all the resources used in try block | Finalize method performs the cleaning activities with respect to the object before its destruction. |
Execution | Final method is executed only when we call it. | Finally block is executed as soon as the try-catch block is executed. It's execution is not dependant on the exception. | Finalize method is executed just before the object is destroyed. |
Java final example
- Class FinalExample{
- Public static void main(String[] args){
- Final int x=100;
- x=200;//Compile Time Error
- }}
Java finally example
- Class FinallyExample{
- Public static void main(String[] args){
- Try{
- Int x=300;
- }catch(Exception e){System.out.println(e);}
- Finally{System.out.println("finally block is executed");}
- }}
Java finalize example
- Class FinalizeExample{
- Public void finalize(){System.out.println("finalize called");}
- Public static void main(String[] args){
- FinalizeExample f1=new FinalizeExample();
- FinalizeExample f2=new FinalizeExample();
- f1=null;
- f2=null;
- System.gc();
- }}
Key takeaway
Java try block is used to enclose the code that might throw an exception. It must be used within the method.
Java catch block is used to handle the Exception by declaring the type of exception within the parameter.
References:
1. T. Budd (2009), An Introduction to Object Oriented Programming, 3rd edition, Pearson Education, India.
2. J. Nino, F. A. Hosch (2002), An Introduction to programming and OO design using Java, John Wiley & sons, New Jersey.
3. Y. Daniel Liang (2010), Introduction to Java programming, 7th edition, Pearson education, India.
4. Object Oriented Programming with C++ by E Balagurusamy, Fifth Edition, TMH.