UNIT - 4. Multithreading Exceptions Assertions
UNIT - 4. Multithreading Exceptions Assertions
Multithreading:
Java Thread
• Thread can be called lightweight process. Thread
requires less resources to create and exists in the
process, thread shares the process resources. A thread
is a single sequential flow of control within a program.
A thread is a:
• Facility to allow multiple activities within a single
process
• Referred as lightweight process
• A thread is a series of executed statements
• Each thread has its own program counter, stack and
local variables
• A thread is a nested sequence of method calls
• Its shares memory, files and per-process state
• The need of a thread or why we use Threads
1 To perform asynchronous or background
processing
2 Increases the responsiveness of GUI applications
3 Take advantage of multiprocessor systems
4 Simplify program logic when there are multiple
independent entities
• When a thread is invoked, there will be two paths
of execution. One path will execute the thread
and the other path will follow the statement after
the thread invocation. There will be a separate
stack and memory space for each thread.
• Thread implementation in java can be
achieved in two ways:
1 Extending the java.lang.Thread class
2 Implementing the java.lang.Runnable Interface
• 1) By extending thread class
• The class should extend Java Thread class.
• The class should override the run() method.
• The functionality that is expected by the Thread to be executed is written in the
run() method.
• void start(): Creates a new thread and makes it runnable.
void run(): The new thread begins its life inside this method.
• Example
public class MyThread extends Thread
{
public void run()
{
System.out.println("thread is running...");
}
public static void main(String[] args)
{
MyThread obj = new MyThread();
obj.start();
}
}
• 2) By Implementing Runnable interface
• The class should implement the Runnable interface
• The class should implement the run() method in the Runnable interface
• The functionality that is expected by the Thread to be executed is put in
the run() method
• Example:
public class MyThread implements Runnable
{
public void run()
{
System.out.println("thread is running..");
}
public static void main(String[] args)
{
Thread t = new Thread(new MyThread());
t.start();
}
}
• Extends Thread class vs Implements Runnable
Interface.
• Extending the Thread class will make your class unable
to extend other classes, because of the single
inheritance feature in JAVA. However, this will give you
a simpler code structure. If you implement Runnable,
you can gain better object-oriented design and
consistency and also avoid the single inheritance
problems.
• If you just want to achieve basic functionality of a
thread you can simply implement Runnable interface
and override run() method. But if you want to do
something serious with thread object as it has other
methods like suspend(), resume(), ..etc which are not
available in Runnable interface then you may prefer to
extend the Thread class.
Lifecycle and States of a Thread
• A thread in Java at any point of time exists in
any one of the following states. A thread lies
only in one of the shown states at any instant:
• New
• Runnable
• Blocked
• Waiting
• Timed Waiting
• Terminated
1) New Thread: When a new thread is created, it is in the new state. The thread has not yet started to run
when thread is in this state. When a thread lies in the new state, it’s code is yet to be run and hasn’t
started to execute.
2) Runnable State: A thread that is ready to run is moved to runnable state. In this state, a thread might
actually be running or it might be ready run at any instant of time. It is the responsibility of the thread
scheduler to give the thread, time to run.
A multi-threaded program allocates a fixed amount of time to each individual thread. Each and every
thread runs for a short while and then pauses and relinquishes the CPU to another thread, so that other
threads can get a chance to run. When this happens, all such threads that are ready to run, waiting for
the CPU and the currently running thread lies in runnable state.
3) Blocked/Waiting state:When a thread is temporarily inactive, then it’s in one of the following states:
– Blocked
– Waiting
• For example, when a thread is waiting for I/O to complete, it lies in the blocked state. It’s the responsibility
of the thread scheduler to reactivate and schedule a blocked/waiting thread. A thread in this state cannot
continue its execution any further until it is moved to runnable state. Any thread in these states does not
consume any CPU cycle.
• A thread is in the blocked state when it tries to access a protected section of code that is currently locked
by some other thread. When the protected section is unlocked, the schedule picks one of the thread
which is blocked for that section and moves it to the runnable state. Whereas, a thread is in the waiting
state when it waits for another thread on a condition. When this condition is fulfilled, the scheduler is
notified and the waiting thread is moved to runnable state.
• If a currently running thread is moved to blocked/waiting state, another thread in the runnable state is
scheduled by the thread scheduler to run. It is the responsibility of thread scheduler to determine which
thread to run.
4) Timed Waiting: A thread lies in timed waiting state when it calls a method with a time out parameter. A
thread lies in this state until the timeout is completed or until a notification is received. For example,
when a thread calls sleep or a conditional wait, it is moved to a timed waiting state.
5) Terminated State: A thread terminates because of either of the following reasons:
– Because it exists normally. This happens when the code of thread has entirely executed by the
program.
– Because there occurred some unusual erroneous event, like segmentation fault or an unhandled
exception.
• A thread that lies in a terminated state does no longer consumes any cycles of CPU.
Interrupting a Thread:
• If any thread is in sleeping or waiting state (i.e. sleep()
or wait() is invoked), calling the interrupt() method on
the thread, breaks out the sleeping or waiting state
throwing InterruptedException.
• If the thread is not in the sleeping or waiting state,
calling the interrupt() method performs normal
behavior and doesn't interrupt the thread but sets the
interrupt flag to true. Let's first see the methods
provided by the Thread class for thread interruption.
• The 3 methods provided by the Thread class for
interrupting a thread
• public void interrupt()
• public static boolean interrupted()
• public boolean isInterrupted()
Example of interrupting a thread that
stops working
• In this example, after interrupting the thread,
we are propagating it, so it will stop working.
If we don't want to stop the thread, we can
handle it where sleep() or wait() method is
invoked.
• class TestInterruptingThread1 extends Thread{
• public void run(){
• try{
• Thread.sleep(1000);
• System.out.println("task");
• }catch(InterruptedException e){
• throw new RuntimeException("Thread interrupted..."+e);
• }
•
• }
•
• public static void main(String args[]){
• TestInterruptingThread1 t1=new TestInterruptingThread1();
• t1.start();
• try{
• t1.interrupt();
• }catch(Exception e){System.out.println("Exception handled "+e);}
•
• }
• }
• Output:Exception in thread-0
• java.lang.RuntimeException: Thread interrupted...
• java.lang.InterruptedException: sleep interrupted
• at A.run(A.java:7)
• Example of interrupting thread that behaves normally
• If thread is not in sleeping or waiting state, calling the interrupt() method sets the interrupted flag
to true that can be used to stop the thread by the java programmer later.
• class TestInterruptingThread3 extends Thread{
•
• public void run(){
• for(int i=1;i<=5;i++)
• System.out.println(i);
• }
•
• public static void main(String args[]){
• TestInterruptingThread3 t1=new TestInterruptingThread3();
• t1.start();
•
• t1.interrupt();
•
• }
• }
Output:
1
2
3
4
5
Thread Properties
• Each thread have a priority. Priorities are represented by a number
between 1 and 10. In most cases, thread schedular schedules the threads
according to their priority (known as preemptive scheduling). 1 is the min
priority and 10 is the max priority. But it is not guaranteed because it
depends on JVM specification that which scheduling it chooses.
• Thread Priorities determines how a thread should be treated with respect
to others.
• Several threads executes concurrently. Every thread has some priority.
• Which thread will get a chance first to execute it is decided by thread
scheduler based on thread priority.
3 constants defined in Thread class:
1) public static int MIN_PRIORITY
2) public static int NORM_PRIORITY
3) public static int MAX_PRIORITY
Default priority of a thread is 5 (NORM_PRIORITY). The value of
MIN_PRIORITY is 1 and the value of MAX_PRIORITY is 10.
• Syntax:
• Thread.MIN_PRIORITY Thread.NORM_PRIORITY Thread.MAX_PRIORITY
• Example of priority of a Thread:
• class TestMultiPriority1 extends Thread{
• public void run(){
• System.out.println("running thread name is:"+Thread.currentThread().getName());
• System.out.println("running thread priority is:"+Thread.currentThread().getPriority());
•
• }
• public static void main(String args[]){
• TestMultiPriority1 m1=new TestMultiPriority1();
• TestMultiPriority1 m2=new TestMultiPriority1();
• m1.setPriority(Thread.MIN_PRIORITY);
• m2.setPriority(Thread.MAX_PRIORITY);
• m1.start();
• m2.start();
•
• }
• }
• Output:running thread name is:Thread-0
• running thread priority is:10
• running thread name is:Thread-1
• running thread priority is:1
Synchronization
• Multi-threaded programs may often come to a situation
where multiple threads try to access the same resources
and finally produce erroneous and unforeseen results.
• So it needs to be made sure by some synchronization
method that only one thread can access the resource at a
given point of time.
• Synchronization in java is the capability to control the
access of multiple threads to any shared resource.
• Java provides a way of creating threads and synchronizing
their task by using synchronized blocks. Synchronized
blocks in Java are marked with the synchronized keyword.
• A synchronized block in Java is synchronized on some
object. All synchronized blocks synchronized on the same
object can only have one thread executing inside them at a
time.
• Types of Synchronization
• There are two types of synchronization
1) Process Synchronization
2) Thread Synchronization
Thread Synchronization
• There are two types of thread synchronization mutual exclusive and inter-thread
communication.
• Mutual Exclusive
– Synchronized method.
– Synchronized block.
– static synchronization.
• Cooperation (Inter-thread communication in java)
Mutual Exclusive
• Mutual Exclusive helps keep threads from interfering with one another while
sharing data. This can be done by three ways in java:
• by synchronized method
• by synchronized block
• by static 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.
• //example of java synchronized method
• class Table{
• synchronized void printTable(int n){//synchronized method
• 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);
• }
• }
• public class TestSynchronization2{
• 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 10 15 20 25 100 200 300 400 500
Thread-Safe Collections
• The Collections class of java.util package
methods that exclusively work on collections
these methods provide various additional
operations which involves polymorphic
algorithms.
• This class provides different variants of the
synchronized Collection() method as shown
below −
Sr. No. Method & Descriptions
1 static <T> Collection<T> synchronized Collection(Collection<T> c)
This method accepts any collection object and, returns a synchronized
(thread-safe) collection backed by the specified collection.
2 static <T> List<T> synchronized List(List<T> list)
This method accepts an object of the List interface returns a
synchronized (thread-safe) list backed by the specified list.
3 static <K,V> Map<K,V> synchronized Map(Map<K,V> m)
This method accepts an object of the Map interface and, returns a
synchronized (thread-safe) map backed by the specified map.
4 static <T> Set<T> synchronized Set(Set<T> s)
This method accepts an object of Set interface and, returns a
synchronized (thread-safe) set backed by the specified set.
5 static <K,V> SortedMap<K,V> synchronized
SortedMap(SortedMap<K,V> m)
This method accepts an object of the Map interface and, returns a
synchronized (thread-safe) sorted map backed by the specified sorted
map.
6 static <T> SortedSet<T> synchronized SortedSet(SortedSet<T> s)
This method accepts an object of the synchronized SortedSet interface
and, returns a synchronized (thread-safe) sorted set backed by the
specified sorted set.
• Example
• import java.util.Collection;
• import java.util.Collections;
• import java.util.Vector;
• public class CollectionReadOnly
• {
• public static void main(String[] args)
• { //Instantiating an ArrayList object
• Vector<String> vector = new Vector<String>();
• vector.add("JavaFx");
• vector.add("Java");
• vector.add("WebGL");
• vector.add("OpenCV");
• System.out.println(vector);
• Collection<String> synchronized Vector = Collections.synchronized Collection(vector);
• System.out.println("Synchronized "+synchronized Vector);
• synchronized Vector.add("Coffee Script");
• }
• }
• Output
• [JavaFx, Java, WebGL, OpenCV]
• Synchronized [JavaFx, Java, WebGL, OpenCV]
Thread Class Methods
ThreadGroup
ThreadGroup in Java
• Java provides a convenient way to group multiple threads in a single object. In such a way, we
can suspend, resume or interrupt a group of threads by a single method call.
• Note: Now suspend(), resume() and stop() methods are deprecated.
• Java thread group is implemented by java.lang.ThreadGroup class.
• A ThreadGroup represents a set of threads. A thread group can also include the other thread
group. The thread group creates a tree in which every thread group except the initial thread
group has a parent.
• A thread is allowed to access information about its own thread group, but it cannot access
the information about its thread group's parent thread group or any other thread groups.
• Constructors of ThreadGroup class-There are only two constructors of ThreadGroup class.
System.out.println(num);
} catch(NumberFormatException e) {
System.out.println("Number format exception");
}
}
• } Output: Number format exception
User-Defined Exceptions
• Sometimes, the built-in exceptions in Java are not able to describe a certain situation. In such cases,
user can also create exceptions which are called ‘user-defined Exceptions’.
Following steps are followed for the creation of user-defined Exception.
• The user should create an exception class as a subclass of Exception class. Since all the exceptions
are subclasses of Exception class, the user should also make his class a subclass of it. This is done
as:
• class MyException extends Exception
• We can write a default constructor in his own exception class.
• MyException(){}
• We can also create a parameterized constructor with a string as a parameter.
We can use this to store exception details. We can call super class(Exception) constructor from this
and send the string there.
• MyException(String str)
• {
super(str);
}
• To raise exception of user-defined type, we need to create an object to his exception class and
throw it using throw clause, as:
• MyException me = new MyException(“Exception details”);
• throw me;
• The following program illustrates how to create
own exception class MyException.
• Details of account numbers, customer names,
and balance amounts are taken in the form of
three arrays.
• In main() method, the details are displayed using
a for-loop. At this time, check is done if in any
account the balance amount is less than the
minimum balance amount to be ept in the
account.
• If it is so, then MyException is raised and a
message is displayed “Balance amount is less”.
• // Java program to demonstrate user defined exception
• // default constructor
• MyException() { }
• // parametrized constructor
• MyException(String str) { super(str); }
• // write main()
•
• public static void main(String[] args)
• {
• try {
• // display the heading for the table
• System.out.println("ACCNO" + "\t" + "CUSTOMER" +
• "\t" + "BALANCE");
•
• // display the actual account information
• for (int i = 0; i < 5 ; i++)
• {
• System.out.println(accno[i] + "\t" + name[i] +
• "\t" + bal[i]);
•
• // display own exception if balance < 1000
• if (bal[i] < 1000)
• {
• MyException me =
• new MyException("Balance is less than 1000");
• throw me;
• }
• }
• } //end of try
•
• catch (MyException e) {
• e.printStackTrace();
• }
• }
• }
• RunTime Error
• MyException: Balance is less than 1000 at MyException.main(fileProperty.java:36)
• Output:
• ACCNO CUSTOMER BALANCE
1001 Nish 10000.0
1002 Shubh 12000.0
1003 Sush 5600.0
1004 Abhi 999.0
Assertions
• An assertion is a statement in Java which ensures the correctness of any assumptions which have been done in
the program. When an assertion is executed, it is assumed to be true. If the assertion is false, the JVM will throw
an Assertion error. It finds it application primarily in the testing purposes. Assertion statements are used along
with boolean expressions.
• Assertions in Java can be done with the help of the assert keyword. There are two ways in which an assert
statement can be used.
First Way −
assert expression;
Second Way −
assert expression1 : expression2
By default, assertions are disabled in Java. In order to enable them we use the following command −
java -ea Example (or)
java –enable assertions Example
where Example is the name of the Java file.
Let us see an example for generation of an assertion error by the JVM −
Example
public class Example
{ public static void main(String[] args)
{ int age = 14; assert age <= 18 : "Cannot Vote"; System.out.println("The voter's age is " + age);
}
}
Output
The voter's age is 14