0% found this document useful (0 votes)
6 views57 pages

File Handling and Multithreading in Java

Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
6 views57 pages

File Handling and Multithreading in Java

Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 57

File handling in Java

File handling in Java involves reading from and writing to files on the disk. Java
provides several classes and methods in the java.io and java.io packages to perform
these operations. Here's a simplified explanation and example of file handling in
Java.

Basic Operations
Reading from a File: You can use classes like FileReader and BufferedReader to
read text from a file.
Writing to a File: You can use classes like FileWriter and BufferedWriter to write
text to a file.
Appending to a File: You can open a file in append mode to add text to the end of
the file without overwriting the existing content.

Java I/O (Input and Output) is used to process the input and produce the output.

Java uses the concept of a stream to make I/O operation fast. The java.io package
contains all the classes required for input and output operations.

We can perform file handling in Java by Java I/O API.

Stream

A stream is a sequence of data. In Java, a stream is composed of bytes. It's called a


stream because it is like a stream of water that continues to flow.

In Java, 3 streams are created for us automatically. All these streams are attached
with the console.

1) System.out: standard output stream

2) System.in: standard input stream


3) System.err: standard error stream

Let's see the code to print output and an error message to the console.

1. System.out.println("simple message");
2. System.err.println("error message");

Let's see the code to get input from console.

1. int i=System.in.read();//returns ASCII code of 1st character


2. System.out.println((char)i);//will print the character

OutputStream vs InputStream

The explanation of OutputStream and InputStream classes are given below:

OutputStream

Java application uses an output stream to write data to a destination; it may be a file,
an array, peripheral device or socket.

InputStream

Java application uses an input stream to read data from a source; it may be a file, an
array, peripheral device or socket.

Let's understand the working of Java OutputStream and InputStream by the figure
given below.
OutputStream class

OutputStream class is an abstract class. It is the superclass of all classes representing


an output stream of bytes. An output stream accepts output bytes and sends them to
some sink.

Useful methods of OutputStream

Method Description

1) public void write(int)throws is used to write a byte to the current output


IOException stream.

2) public void write(byte[])throws is used to write an array of byte to the


IOException current output stream.

3) public void flush()throws flushes the current output stream.


IOException

4) public void close()throws is used to close the current output stream.


IOException

OutputStream Hierarchy
InputStream class

InputStream class is an abstract class. It is the superclass of all classes representing


an input stream of bytes.

Useful methods of InputStream

Method Description

1) public abstract int reads the next byte of data from the input stream. It
read()throws IOException returns -1 at the end of the file.

2) public int available()throws returns an estimate of the number of bytes that can
IOException be read from the current input stream.

3) public void close()throws is used to close the current input stream.


IOException

InputStream Hierarchy
Java Console Class
The Java Console class is be used to get input from console. It provides methods to
read texts and passwords.

If you read password using Console class, it will not be displayed to the user.

The java.io.Console class is attached with system console internally. The Console
class is introduced since 1.5.

Let's see a simple example to read text from console.

1. String text=System.console().readLine();
2. System.out.println("Text is: "+text);

Java Console class declaration

Let's see the declaration for Java.io.Console class:

1. public final class Console extends Object implements Flushable

Java Console class methods

Method Description

Reader reader() It is used to retrieve the reader object associated


with the console

String readLine() It is used to read a single line of text from the


console.

String readLine(String fmt, It provides a formatted prompt then reads the


Object... args) single line of text from the console.
char[] readPassword() It is used to read password that is not being
displayed on the console.

char[] readPassword(String It provides a formatted prompt then reads the


fmt, Object... args) password that is not being displayed on the
console.

Console format(String fmt, It is used to write a formatted string to the


Object... args) console output stream.

Console printf(String format, It is used to write a string to the console output


Object... args) stream.

PrintWriter writer() It is used to retrieve the PrintWriter object


associated with the console.

void flush() It is used to flushes the console.

How to get the object of Console

System class provides a static method console() that returns the singleton instance
of Console class.

1. public static Console console(){}

Let's see the code to get the instance of Console class.

1. Console c=System.console();

Java Console Example

1. import java.io.Console;
2. class ReadStringTest{
3. public static void main(String args[]){
4. Console c=System.console();
5. System.out.println("Enter your name: ");
6. String n=c.readLine();
7. System.out.println("Welcome "+n);
8. }
9. }

Output

Enter your name: Nakul Jain


Welcome Nakul Jain

Java Console Example to read password

1. import java.io.Console;
2. class ReadPasswordTest{
3. public static void main(String args[]){
4. Console c=System.console();
5. System.out.println("Enter password: ");
6. char[] ch=c.readPassword();
7. String pass=String.valueOf(ch);//converting char array into string
8. System.out.println("Password is: "+pass);
9. }
10.}

Output

Enter password:
Password is: 123
Multithreading in Java
Multithreading in Java is a process of executing multiple threads simultaneously.

A thread is a lightweight sub-process, the smallest unit of processing.


Multiprocessing and multithreading, both are used to achieve multitasking.

However, we use multithreading than multiprocessing because threads use a shared


memory area. They don't allocate separate memory area so saves memory, and
context-switching between the threads takes less time than process.

Java Multithreading is mostly used in games, animation, etc.

Advantages of Java Multithreading

1) It doesn't block the user because threads are independent and you can perform
multiple operations at the same time.

2) You can perform many operations together, so it saves time.

3) Threads are independent, so it doesn't affect other threads if an exception occurs


in a single thread.

Multitasking

Multitasking is a process of executing multiple tasks simultaneously. We use


multitasking to utilize the CPU. Multitasking can be achieved in two ways:

o Process-based Multitasking (Multiprocessing)


o Thread-based Multitasking (Multithreading)

1) Process-based Multitasking (Multiprocessing)

o Each process has an address in memory. In other words, each process allocates
a separate memory area.
o A process is heavyweight.
o Cost of communication between the process is high.
o Switching from one process to another requires some time for saving and
loading registers, memory maps, updating lists, etc.

2) Thread-based Multitasking (Multithreading)

o Threads share the same address space.


o A thread is lightweight.
o Cost of communication between the thread is low.

Note: At least one process is required for each thread.

What is Thread in java

A thread is a lightweight subprocess, the smallest unit of processing. It is a separate


path of execution.

Threads are independent. If there occurs exception in one thread, it doesn't affect
other threads. It uses a shared memory area.
As shown in the above figure, a thread is executed inside the process. There is
context-switching between the threads. There can be multiple processes inside
the OS, and one process can have multiple threads.

Note: At a time one thread is executed only.

Java Thread class

Java provides Thread class to achieve thread programming. Thread class


provides constructors and methods to create and perform operations on a thread.
Thread class extends Object class and implements Runnable interface.

Java Thread Methods


Java Thread Methods

Modifier and Type Method Description

1) void start() It is used to


start the
execution of
the thread.

2) void run() It is used to do


an action for a
thread.

3) static void sleep() It sleeps a


thread for the
specified
amount of
time.

4) static Thread currentThread() It returns a


reference to
the currently
executing
thread object.

5) void join() It waits for a


thread to die.

6) int getPriority() It returns the


priority of the
thread.

7) void setPriority() It changes the


priority of the
thread.

8) String getName() It returns the


name of the
thread.
9) void setName() It changes the
name of the
thread.

10) long getId() It returns the


id of the
thread.

11) boolean isAlive() It tests if the


thread is alive.

12) static void yield() It causes the


currently
executing
thread object
to pause and
allow other
threads to
execute
temporarily.

13) void suspend() It is used to


suspend the
thread.

14) void resume() It is used to


resume the
suspended
thread.

15) void stop() It is used to


stop the
thread.

16) void destroy() It is used to


destroy the
thread group
and all of its
subgroups.
17) boolean isDaemon() It tests if the
thread is a
daemon
thread.

18) void setDaemon() It marks the


thread as
daemon or
user thread.

19) void interrupt() It interrupts


the thread.

20) boolean isinterrupted() It tests


whether the
thread has
been
interrupted.

21) static boolean interrupted() It tests


whether the
current thread
has been
interrupted.

22) static int activeCount() It returns the


number of
active threads
in the current
thread's
thread group.

23) void checkAccess() It determines


if the currently
running
thread has
permission to
modify the
thread.
24) static boolean holdLock() It returns true
if and only if
the current
thread holds
the monitor
lock on the
specified
object.

25) static void dumpStack() It is used to


print a stack
trace of the
current thread
to the
standard error
stream.

26) StackTraceElement[] getStackTrace() It returns an


array of stack
trace elements
representing
the stack
dump of the
thread.

27) static int enumerate() It is used to


copy every
active thread's
thread group
and its
subgroup into
the specified
array.

28) Thread.State getState() It is used to


return the
state of the
thread.
29) ThreadGroup getThreadGroup() It is used to
return the
thread group
to which this
thread
belongs

30) String toString() It is used to


return a string
representation
of this thread,
including the
thread's name,
priority, and
thread group.

31) void notify() It is used to


give the
notification
for only one
thread which
is waiting for a
particular
object.

32) void notifyAll() It is used to


give the
notification to
all waiting
threads of a
particular
object.

33) void setContextClassLoader() It sets the


context
ClassLoader
for the Thread.

34) ClassLoader getContextClassLoader() It returns the


context
ClassLoader
for the thread.

35) static getDefaultUncaughtExceptionHandler() It returns the


Thread.UncaughtExceptionHandler default
handler
invoked when
a thread
abruptly
terminates
due to an
uncaught
exception.

36) static void setDefaultUncaughtExceptionHandler() It sets the


default
handler
invoked when
a thread
abruptly
terminates
due to an
uncaught
exception.
Life cycle of a Thread (Thread States)
In Java, a thread always exists in any one of the following states. These states are:

1. New
2. Active
3. Blocked / Waiting
4. Timed Waiting
5. Terminated

Explanation of Different Thread States

New: Whenever a new thread is created, it is always in the new state. For a thread
in the new state, the code has not been run yet and thus has not begun its execution.

Active: When a thread invokes the start() method, it moves from the new state to the
active state. The active state contains two states within it: one is runnable, and the
other is running.

o Runnable: A thread, that is ready to run is then moved to the runnable state.
In the runnable state, the thread may be running or may be ready to run at any
given instant of time. It is the duty of the thread scheduler to provide the thread
time to run, i.e., moving the thread the running state.
A program implementing multithreading acquires a fixed slice of time to each
individual thread. Each and every thread runs for a short span of time and
when that allocated time slice is over, the thread voluntarily gives up the CPU
to the other thread, so that the other threads can also run for their slice of time.
Whenever such a scenario occurs, all those threads that are willing to run,
waiting for their turn to run, lie in the runnable state. In the runnable state,
there is a queue where the threads lie.
o Running: When the thread gets the CPU, it moves from the runnable to the
running state. Generally, the most common change in the state of a thread is
from runnable to running and again back to runnable.

Blocked or Waiting: Whenever a thread is inactive for a span of time (not


permanently) then, either the thread is in the blocked state or is in the waiting state.
For example, a thread (let's say its name is A) may want to print some data from the
printer. However, at the same time, the other thread (let's say its name is B) is using
the printer to print some data. Therefore, thread A has to wait for thread B to use the
printer. Thus, thread A is in the blocked state. A thread in the blocked state is unable
to perform any execution and thus never consume any cycle of the Central
Processing Unit (CPU). Hence, we can say that thread A remains idle until the thread
scheduler reactivates thread A, which is in the waiting or blocked state.

When the main thread invokes the join() method then, it is said that the main thread
is in the waiting state. The main thread then waits for the child threads to complete
their tasks. When the child threads complete their job, a notification is sent to the
main thread, which again moves the thread from waiting to the active state.

If there are a lot of threads in the waiting or blocked state, then it is the duty of the
thread scheduler to determine which thread to choose and which one to reject, and
the chosen thread is then given the opportunity to run.

Timed Waiting: Sometimes, waiting for leads to starvation. For example, a thread
(its name is A) has entered the critical section of a code and is not willing to leave
that critical section. In such a scenario, another thread (its name is B) has to wait
forever, which leads to starvation. To avoid such scenario, a timed waiting state is
given to thread B. Thus, thread lies in the waiting state for a specific span of time,
and not forever. A real example of timed waiting is when we invoke the sleep()
method on a specific thread. The sleep() method puts the thread in the timed wait
state. After the time runs out, the thread wakes up and start its execution from when
it has left earlier.

Terminated: A thread reaches the termination state because of the following


reasons:

o When a thread has finished its job, then it exists or terminates normally.
o Abnormal termination: It occurs when some unusual events such as an
unhandled exception or segmentation fault.

A terminated thread means the thread is no more in the system. In other words, the
thread is dead, and there is no way one can respawn (active after kill) the dead thread.

The following diagram shows the different states involved in the life cycle of a
thread.
Implementation of Thread States

In Java, one can get the current state of a thread using


the Thread.getState() method. The java.lang.Thread.State class of Java provides
the constants ENUM to represent the state of a thread. These constants are:

1. public static final Thread.State NEW

It represents the first state of a thread that is the NEW state.

1. public static final Thread.State RUNNABLE

It represents the runnable state.It means a thread is waiting in the queue to run.

1. public static final Thread.State BLOCKED

It represents the blocked state. In this state, the thread is waiting to acquire a lock.

1. public static final Thread.State WAITING

It represents the waiting state. A thread will go to this state when it invokes the
Object.wait() method, or Thread.join() method with no timeout. A thread in the
waiting state is waiting for another thread to complete its task.

1. public static final Thread.State TIMED_WAITING


It represents the timed waiting state. The main difference between waiting and timed
waiting is the time constraint. Waiting has no time constraint, whereas timed waiting
has the time constraint. A thread invoking the following method reaches the timed
waiting state.

o sleep
o join with timeout
o wait with timeout
o parkUntil
o parkNanos

1. public static final Thread.State TERMINATED

It represents the final state of a thread that is terminated or dead. A terminated thread
means it has completed its execution.

Java Program for Demonstrating Thread States

The following Java program shows some of the states of a thread defined above.

FileName: ThreadState.java

1. // ABC class implements the interface Runnable


2. class ABC implements Runnable
3. {
4. public void run()
5. {
6.
7. // try-catch block
8. try
9. {
10.// moving thread t2 to the state timed waiting
11.Thread.sleep(100);
12.}
13.catch (InterruptedException ie)
14.{
15.ie.printStackTrace();
16.}
17.
18.
19.System.out.println("The state of thread t1 while it invoked the method join()
on thread t2 -"+ ThreadState.t1.getState());
20.
21.// try-catch block
22.try
23.{
24.Thread.sleep(200);
25.}
26.catch (InterruptedException ie)
27.{
28.ie.printStackTrace();
29.}
30.}
31.}
32.
33.// ThreadState class implements the interface Runnable
34.public class ThreadState implements Runnable
35.{
36.public static Thread t1;
37.public static ThreadState obj;
38.
39.// main method
40.public static void main(String argvs[])
41.{
42.// creating an object of the class ThreadState
43.obj = new ThreadState();
44.t1 = new Thread(obj);
45.
46.// thread t1 is spawned
47.// The thread t1 is currently in the NEW state.
48.System.out.println("The state of thread t1 after spawning it - " + t1.getState()
);
49.
50.// invoking the start() method on
51.// the thread t1
52.t1.start();
53.
54.// thread t1 is moved to the Runnable state
55.System.out.println("The state of thread t1 after invoking the method start() o
n it - " + t1.getState());
56.}
57.
58.public void run()
59.{
60.ABC myObj = new ABC();
61.Thread t2 = new Thread(myObj);
62.
63.// thread t2 is created and is currently in the NEW state.
64.System.out.println("The state of thread t2 after spawning it - "+ t2.getState()
);
65.t2.start();
66.
67.// thread t2 is moved to the runnable state
68.System.out.println("the state of thread t2 after calling the method start() on it
- " + t2.getState());
69.
70.// try-catch block for the smooth flow of the program
71.try
72.{
73.// moving the thread t1 to the state timed waiting
74.Thread.sleep(200);
75.}
76.catch (InterruptedException ie)
77.{
78.ie.printStackTrace();
79.}
80.
81.System.out.println("The state of thread t2 after invoking the method sleep()
on it - "+ t2.getState() );
82.
83.// try-catch block for the smooth flow of the program
84.try
85.{
86.// waiting for thread t2 to complete its execution
87.t2.join();
88.}
89.catch (InterruptedException ie)
90.{
91.ie.printStackTrace();
92.}
93.System.out.println("The state of thread t2 when it has completed it's executi
on - " + t2.getState());
94.}
95.
96.}

Output:

The state of thread t1 after spawning it - NEW


The state of thread t1 after invoking the method start() on it - RUNNABLE
The state of thread t2 after spawning it - NEW
the state of thread t2 after calling the method start() on it - RUNNABLE
The state of thread t1 while it invoked the method join() on thread t2 -
TIMED_WAITING
The state of thread t2 after invoking the method sleep() on it - TIMED_WAITING
The state of thread t2 when it has completed it's execution - TERMINATED

Explanation: Whenever we spawn a new thread, that thread attains the new state.
When the method start() is invoked on a thread, the thread scheduler moves that
thread to the runnable state. Whenever the join() method is invoked on any thread
instance, the current thread executing that statement has to wait for this thread to
finish its execution, i.e., move that thread to the terminated state. Therefore, before
the final print statement is printed on the console, the program invokes the method
join() on thread t2, making the thread t1 wait while the thread t2 finishes its
execution and thus, the thread t2 get to the terminated or dead state. Thread t1 goes
to the waiting state because it is waiting for thread t2 to finish it's execution as it has
invoked the method join() on thread t2.
Java Threads | How to create a thread in Java
There are two ways to create a thread:

1. By extending Thread class


2. By implementing Runnable interface.

Thread class:

Thread class provide constructors and methods to create and perform operations on
a thread.Thread class extends Object class and implements Runnable interface.

Commonly used Constructors of Thread class:

o Thread()
o Thread(String name)
o Thread(Runnable r)
o Thread(Runnable r,String name)

Commonly used methods of Thread class:

1. public void run(): is used to perform action for a thread.


2. public void start(): starts the execution of the thread.JVM calls the run()
method on the thread.
3. public void sleep(long miliseconds): Causes the currently executing thread
to sleep (temporarily cease execution) for the specified number of
milliseconds.
4. public void join(): waits for a thread to die.
5. public void join(long miliseconds): waits for a thread to die for the specified
miliseconds.
6. public int getPriority(): returns the priority of the thread.
7. public int setPriority(int priority): changes the priority of the thread.
8. public String getName(): returns the name of the thread.
9. public void setName(String name): changes the name of the thread.
10.public Thread currentThread(): returns the reference of currently executing
thread.
11.public int getId(): returns the id of the thread.
12.public Thread.State getState(): returns the state of the thread.
13.public boolean isAlive(): tests if the thread is alive.
14.public void yield(): causes the currently executing thread object to
temporarily pause and allow other threads to execute.
15.public void suspend(): is used to suspend the thread(depricated).
16.public void resume(): is used to resume the suspended thread(depricated).
17.public void stop(): is used to stop the thread(depricated).
18.public boolean isDaemon(): tests if the thread is a daemon thread.
19.public void setDaemon(boolean b): marks the thread as daemon or user
thread.
20.public void interrupt(): interrupts the thread.
21.public boolean isInterrupted(): tests if the thread has been interrupted.
22.public static boolean interrupted(): tests if the current thread has been
interrupted.

Runnable interface:

The Runnable interface should be implemented by any class whose instances are
intended to be executed by a thread. Runnable interface have only one method
named run().

1. public void run(): is used to perform action for a thread.

Starting a thread:

The start() method of Thread class is used to start a newly created thread. It
performs the following tasks:

o A new thread starts(with new callstack).


o The thread moves from New state to the Runnable state.
o When the thread gets a chance to execute, its target run() method will run.

1) Java Thread Example by extending Thread class

FileName: Multi.java

1. class Multi extends Thread{


2. public void run(){
3. System.out.println("thread is running...");
4. }
5. public static void main(String args[]){
6. Multi t1=new Multi();
7. t1.start();
8. }
9. }

Output:

thread is running...

2) Java Thread Example by implementing Runnable interface

FileName: Multi3.java

1. class Multi3 implements Runnable{


2. public void run(){
3. System.out.println("thread is running...");
4. }
5.
6. public static void main(String args[]){
7. Multi3 m1=new Multi3();
8. Thread t1 =new Thread(m1); // Using the constructor Thread(Runnable r)
9. t1.start();
10. }
11.}
Output:

thread is running...

If you are not extending the Thread class, your class object would not be treated as
a thread object. So you need to explicitly create the Thread class object. We are
passing the object of your class that implements Runnable so that your class run()
method may execute.

3) Using the Thread Class: Thread(String Name)

We can directly use the Thread class to spawn new threads using the constructors
defined above.

FileName: MyThread1.java

1. public class MyThread1


2. {
3. // Main method
4. public static void main(String argvs[])
5. {
6. // creating an object of the Thread class using the constructor Thread(String
name)
7. Thread t= new Thread("My first thread");
8.
9. // the start() method moves the thread to the active state
10.t.start();
11.// getting the thread name by invoking the getName() method
12.String str = t.getName();
13.System.out.println(str);
14.}
15.}

Output:

My first thread
4) Using the Thread Class: Thread(Runnable r, String name)

Observe the following program.

FileName: MyThread2.java

1. public class MyThread2 implements Runnable


2. {
3. public void run()
4. {
5. System.out.println("Now the thread is running ...");
6. }
7.
8. // main method
9. public static void main(String argvs[])
10.{
11.// creating an object of the class MyThread2
12.Runnable r1 = new MyThread2();
13.
14.// creating an object of the class Thread using Thread(Runnable r, String na
me)
15.Thread th1 = new Thread(r1, "My new thread");
16.
17.// the start() method moves the thread to the active state
18.th1.start();
19.
20.// getting the thread name by invoking the getName() method
21.String str = th1.getName();
22.System.out.println(str);
23.}
24.}

Output:

My new thread
Now the thread is running ...
Thread Scheduler in Java
A component of Java that decides which thread to run or execute and which thread
to wait is called a thread scheduler in Java. In Java, a thread is only chosen by a
thread scheduler if it is in the runnable state. However, if there is more than one
thread in the runnable state, it is up to the thread scheduler to pick one of the
threads and ignore the other ones. There are some criteria that decide which thread
will execute first. There are two factors for scheduling a thread i.e. Priority and
Time of arrival.

Priority: Priority of each thread lies between 1 to 10. If a thread has a higher
priority, it means that thread has got a better chance of getting picked up by the
thread scheduler.

Time of Arrival: Suppose two threads of the same priority enter the runnable
state, then priority cannot be the factor to pick a thread from these two threads. In
such a case, arrival time of thread is considered by the thread scheduler. A thread
that arrived first gets the preference over the other threads.

Thread Scheduler Algorithms

On the basis of the above-mentioned factors, the scheduling algorithm is followed


by a Java thread scheduler.

First Come First Serve Scheduling:

In this scheduling algorithm, the scheduler picks the threads thar arrive first in the
runnable queue. Observe the following table:

Threads Time of Arrival


t1 0
t2 1
t3 2
t4 3

In the above table, we can see that Thread t1 has arrived first, then Thread t2, then
t3, and at last t4, and the order in which the threads will be processed is according
to the time of arrival of threads.
Hence, Thread t1 will be processed first, and Thread t4 will be processed last.

Time-slicing scheduling:

Usually, the First Come First Serve algorithm is non-preemptive, which is bad as it
may lead to infinite blocking (also known as starvation). To avoid that, some time-
slices are provided to the threads so that after some time, the running thread has to
give up the CPU. Thus, the other waiting threads also get time to run their job.

In the above diagram, each thread is given a time slice of 2 seconds. Thus, after 2
seconds, the first thread leaves the CPU, and the CPU is then captured by Thread2.
The same process repeats for the other threads too.
Preemptive-Priority Scheduling:

The name of the scheduling algorithm denotes that the algorithm is related to the
priority of the threads.

Suppose there are multiple threads available in the runnable state. The thread
scheduler picks that thread that has the highest priority. Since the algorithm is also
preemptive, therefore, time slices are also provided to the threads to avoid
starvation. Thus, after some time, even if the highest priority thread has not
completed its job, it has to release the CPU because of preemption.

Working of the Java Thread Scheduler


Let's understand the working of the Java thread scheduler. Suppose, there are five
threads that have different arrival times and different priorities. Now, it is the
responsibility of the thread scheduler to decide which thread will get the CPU first.

The thread scheduler selects the thread that has the highest priority, and the thread
begins the execution of the job. If a thread is already in runnable state and another
thread (that has higher priority) reaches in the runnable state, then the current
thread is pre-empted from the processor, and the arrived thread with higher priority
gets the CPU time.

When two threads (Thread 2 and Thread 3) having the same priorities and arrival
time, the scheduling will be decided on the basis of FCFS algorithm. Thus, the
thread that arrives first gets the opportunity to execute first.
Suppose there are multiple threads available in the runnable state. The thread
scheduler picks that thread that has the highest priority. Since the algorithm is also
preemptive, therefore, time slices are also provided to the threads to avoid
starvation. Thus, after some time, even if the highest priority thread has not
completed its job, it has to release the CPU because of preemption.

Working of the Java Thread Scheduler

Let's understand the working of the Java thread scheduler. Suppose, there are five
threads that have different arrival times and different priorities. Now, it is the
responsibility of the thread scheduler to decide which thread will get the CPU first.

The thread scheduler selects the thread that has the highest priority, and the thread
begins the execution of the job. If a thread is already in runnable state and another
thread (that has higher priority) reaches in the runnable state, then the current
thread is pre-empted from the processor, and the arrived thread with higher priority
gets the CPU time.

When two threads (Thread 2 and Thread 3) having the same priorities and arrival
time, the scheduling will be decided on the basis of FCFS algorithm. Thus, the
thread that arrives first gets the opportunity to execute first.
Priority of a Thread (Thread Priority)
Each thread has a priority. Priorities are represented by a number between 1 and
10. In most cases, the thread scheduler schedules the threads according to their
priority (known as preemptive scheduling). But it is not guaranteed because it
depends on JVM specification that which scheduling it chooses. Note that not only
JVM a Java programmer can also assign the priorities of a thread explicitly in a
Java program.

Setter & Getter Method of Thread Priority

Let's discuss the setter and getter method of the thread priority.

public final int getPriority(): The java.lang.Thread.getPriority() method returns


the priority of the given thread.

public final void setPriority(int newPriority): The java.lang.Thread.setPriority()


method updates or assign the priority of the thread to newPriority. The method
throws IllegalArgumentException if the value newPriority goes out of the range,
which is 1 (minimum) to 10 (maximum).

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.

Example of priority of a Thread:

FileName: ThreadPriorityExample.java

1. // Importing the required classes


2. import java.lang.*;
3.
4. public class ThreadPriorityExample extends Thread
5. {
6.
7. // Method 1
8. // Whenever the start() method is called by a thread
9. // the run() method is invoked
10.public void run()
11.{
12.// the print statement
13.System.out.println("Inside the run() method");
14.}
15.
16.// the main method
17.public static void main(String argvs[])
18.{
19.// Creating threads with the help of ThreadPriorityExample class
20.ThreadPriorityExample th1 = new ThreadPriorityExample();
21.ThreadPriorityExample th2 = new ThreadPriorityExample();
22.ThreadPriorityExample th3 = new ThreadPriorityExample();
23.
24.// We did not mention the priority of the thread.
25.// Therefore, the priorities of the thread is 5, the default value
26.
27.// 1st Thread
28.// Displaying the priority of the thread
29.// using the getPriority() method
30.System.out.println("Priority of the thread th1 is : " + th1.getPriority());
31.
32.// 2nd Thread
33.// Display the priority of the thread
34.System.out.println("Priority of the thread th2 is : " + th2.getPriority());
35.
36.// 3rd Thread
37.// // Display the priority of the thread
38.System.out.println("Priority of the thread th2 is : " + th2.getPriority());
39.
40.// Setting priorities of above threads by
41.// passing integer arguments
42.th1.setPriority(6);
43.th2.setPriority(3);
44.th3.setPriority(9);
45.
46.// 6
47.System.out.println("Priority of the thread th1 is : " + th1.getPriority());
48.
49.// 3
50.System.out.println("Priority of the thread th2 is : " + th2.getPriority());
51.
52.// 9
53.System.out.println("Priority of the thread th3 is : " + th3.getPriority());
54.
55.// Main thread
56.
57.// Displaying name of the currently executing thread
58.System.out.println("Currently Executing The Thread : " + Thread.currentThr
ead().getName());
59.
60.System.out.println("Priority of the main thread is : " + Thread.currentThread
().getPriority());
61.
62.// Priority of the main thread is 10 now
63.Thread.currentThread().setPriority(10);
64.
65.System.out.println("Priority of the main thread is : " + Thread.currentThread
().getPriority());
66.}
67.}

Output:

Priority of the thread th1 is : 5


Priority of the thread th2 is : 5
Priority of the thread th2 is : 5
Priority of the thread th1 is : 6
Priority of the thread th2 is : 3
Priority of the thread th3 is : 9
Currently Executing The Thread : main
Priority of the main thread is : 5
Priority of the main thread is : 10

We know that a thread with high priority will get preference over lower priority
threads when it comes to the execution of threads. However, there can be other
scenarios where two threads can have the same priority. All of the processing, in
order to look after the threads, is done by the Java thread scheduler. Refer to the
following example to comprehend what will happen if two threads have the same
priority.

FileName: ThreadPriorityExample1.java

1. // importing the java.lang package


2. import java.lang.*;
3.
4. public class ThreadPriorityExample1 extends Thread
5. {
6.
7. // Method 1
8. // Whenever the start() method is called by a thread
9. // the run() method is invoked
10.public void run()
11.{
12.// the print statement
13.System.out.println("Inside the run() method");
14.}
15.
16.
17.// the main method
18.public static void main(String argvs[])
19.{
20.
21.// Now, priority of the main thread is set to 7
22.Thread.currentThread().setPriority(7);
23.
24.// the current thread is retrieved
25.// using the currentThread() method
26.
27.// displaying the main thread priority
28.// using the getPriority() method of the Thread class
29.System.out.println("Priority of the main thread is : " + Thread.currentThread
().getPriority());
30.
31.// creating a thread by creating an object of the class ThreadPriorityExample
1
32.ThreadPriorityExample1 th1 = new ThreadPriorityExample1();
33.
34.// th1 thread is the child of the main thread
35.// therefore, the th1 thread also gets the priority 7
36.
37.// Displaying the priority of the current thread
38.System.out.println("Priority of the thread th1 is : " + th1.getPriority());
39.}
40.}

Output:

Priority of the main thread is : 7


Priority of the thread th1 is : 7

Explanation: If there are two threads that have the same priority, then one can not
predict which thread will get the chance to execute first. The execution then is
dependent on the thread scheduler's algorithm (First Come First Serve, Round-
Robin, etc.)

Example of IllegalArgumentException

We know that if the value of the parameter newPriority of the method getPriority()
goes out of the range (1 to 10), then we get the IllegalArgumentException. Let's
observe the same with the help of an example.

FileName: IllegalArgumentException.java

1. // importing the java.lang package


2. import java.lang.*;
3.
4. public class IllegalArgumentException extends Thread
5. {
6.
7. // the main method
8. public static void main(String argvs[])
9. {
10.
11.// Now, priority of the main thread is set to 17, which is greater than 10
12.Thread.currentThread().setPriority(17);
13.
14.// The current thread is retrieved
15.// using the currentThread() method
16.
17.// displaying the main thread priority
18.// using the getPriority() method of the Thread class
19.System.out.println("Priority of the main thread is : " + Thread.currentThread
().getPriority());
20.
21.}
22.}

When we execute the above program, we get the following exception:

Exception in thread "main" java.lang.IllegalArgumentException


at java.base/java.lang.Thread.setPriority(Thread.java:1141)
at IllegalArgumentException.main(IllegalArgumentException.java:12)
Daemon Thread in Java
Daemon thread in Java is a service provider thread that provides services to the
user thread. Its life depend on the mercy of user threads i.e. when all the user
threads dies, JVM terminates this thread automatically.

There are many java daemon threads running automatically e.g. gc, finalizer etc.

You can see all the detail by typing the jconsole in the command prompt. The
jconsole tool provides information about the loaded classes, memory usage,
running threads etc.

Points to remember for Daemon Thread in Java

 It provides services to user threads for background supporting tasks. It has


no role in life than to serve user threads.
 Its life depends on user threads.
 It is a low priority thread.

Why JVM terminates the daemon thread if there is no user thread?

The sole purpose of the daemon thread is that it provides services to user thread for
background supporting task. If there is no user thread, why should JVM keep
running this thread. That is why JVM terminates the daemon thread if there is no
user thread.

Methods for Java Daemon thread by Thread class

The java.lang.Thread class provides two methods for java daemon thread.

No. Method Description

public void is used to mark the current thread as daemon


1)
setDaemon(boolean status) thread or user thread.

2) public boolean isDaemon() is used to check that current is daemon.

Simple example of Daemon thread in java

File: MyThread.java
1. public class TestDaemonThread1 extends Thread{
2. public void run(){
3. if(Thread.currentThread().isDaemon()){//checking for daemon thread
4. System.out.println("daemon thread work");
5. }
6. else{
7. System.out.println("user thread work");
8. }
9. }
10. public static void main(String[] args){
11. TestDaemonThread1 t1=new TestDaemonThread1();//creating thread
12. TestDaemonThread1 t2=new TestDaemonThread1();
13. TestDaemonThread1 t3=new TestDaemonThread1();
14.
15. t1.setDaemon(true);//now t1 is daemon thread
16.
17. t1.start();//starting threads
18. t2.start();
19. t3.start();
20. }
21.}

Test it Now

Output:

daemon thread work


user thread work
user thread work
Note: If you want to make a user thread as Daemon, it must not be started
otherwise it will throw IllegalThreadStateException.

File: MyThread.java

1. class TestDaemonThread2 extends Thread{


2. public void run(){
3. System.out.println("Name: "+Thread.currentThread().getName());
4. System.out.println("Daemon: "+Thread.currentThread().isDaemon());
5. }
6.
7. public static void main(String[] args){
8. TestDaemonThread2 t1=new TestDaemonThread2();
9. TestDaemonThread2 t2=new TestDaemonThread2();
10. t1.start();
11. t1.setDaemon(true);//will throw exception here
12. t2.start();
13. }
14.}

Test it Now

Output:

exception in thread main: java.lang.IllegalThreadStateException


Thread Group 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.

No. Constructor Description

creates a thread group with given


1) ThreadGroup(String name)
name.

ThreadGroup(ThreadGroup parent, creates a thread group with a given


2)
String name) parent group and name.

Methods of ThreadGroup class

There are many methods in ThreadGroup class. A list of ThreadGroup methods is


given below.

Modifier and
S.N. Method Description
Type
This method determines if the
currently running thread has
1) void checkAccess()
permission to modify the thread
group.

This method returns an estimate of


2) int activeCount() the number of active threads in the
thread group and its subgroups.

This method returns an estimate of


3) int activeGroupCount() the number of active groups in the
thread group and its subgroups.

This method destroys the thread


4) void destroy()
group and all of its subgroups.

This method copies into the


specified array every active thread
5) int enumerate(Thread[] list)
in the thread group and its
subgroups.

This method returns the maximum


6) int getMaxPriority()
priority of the thread group.

This method returns the name of the


7) String getName()
thread group.

This method returns the parent of


8) ThreadGroup getParent()
the thread group.

This method interrupts all threads in


9) void interrupt()
the thread group.

This method tests if the thread


10) boolean isDaemon()
group is a daemon thread group.

setDaemon(boolean This method changes the daemon


11) void
daemon) status of the thread group.
This method tests if this thread
12) boolean isDestroyed()
group has been destroyed.

This method prints information


13) void list() about the thread group to the
standard output.

This method tests if the thread


parentOf(ThreadGroup group is either the thread group
14) boolean
g argument or one of its ancestor
thread groups.

This method is used to suspend all


15) void suspend()
threads in the thread group.

This method is used to resume all


threads in the thread group which
16) void resume()
was suspended using suspend()
method.

This method sets the maximum


17) void setMaxPriority(int pri)
priority of the group.

This method is used to stop all


18) void stop()
threads in the thread group.

This method returns a string


19) String toString()
representation of the Thread group.

Let's see a code to group multiple threads.

1. ThreadGroup tg1 = new ThreadGroup("Group A");


2. Thread t1 = new Thread(tg1,new MyRunnable(),"one");
3. Thread t2 = new Thread(tg1,new MyRunnable(),"two");
4. Thread t3 = new Thread(tg1,new MyRunnable(),"three");

Now all 3 threads belong to one group. Here, tg1 is the thread group name,
MyRunnable is the class that implements Runnable interface and "one", "two" and
"three" are the thread names.
Now we can interrupt all threads by a single line of code only.

1. Thread.currentThread().getThreadGroup().interrupt();

ThreadGroup Example

File: ThreadGroupDemo.java

1. public class ThreadGroupDemo implements Runnable{


2. public void run() {
3. System.out.println(Thread.currentThread().getName());
4. }
5. public static void main(String[] args) {
6. ThreadGroupDemo runnable = new ThreadGroupDemo();
7. ThreadGroup tg1 = new ThreadGroup("Parent ThreadGroup");
8.
9. Thread t1 = new Thread(tg1, runnable,"one");
10. t1.start();
11. Thread t2 = new Thread(tg1, runnable,"two");
12. t2.start();
13. Thread t3 = new Thread(tg1, runnable,"three");
14. t3.start();
15.
16. System.out.println("Thread Group Name: "+tg1.getName());
17. tg1.list();
18.
19. }
20. }

Output:

one
two
three
Thread Group Name: Parent ThreadGroup
java.lang.ThreadGroup[name=Parent ThreadGroup,maxpri=10]
Java - Thread Synchronization
Need of Thread Synchronization?

When we start two or more threads within a program, there may be a situation
when multiple threads try to access the same resource and finally they can produce
unforeseen result due to concurrency issues. For example, if multiple threads try to
write within a same file then they may corrupt the data because one of the threads
can override data or while one thread is opening the same file at the same time
another thread might be closing the same file.

So there is a need to synchronize the action of multiple threads and make sure that
only one thread can access the resource at a given point in time. This is
implemented using a concept called monitors. Each object in Java is associated
with a monitor, which a thread can lock or unlock. Only one thread at a time may
hold a lock on a monitor.

Thread Synchronization in Java

Java programming language provides a very handy way of creating threads and
synchronizing their task by using synchronized blocks. You keep shared resources
within this block. Following is the general form of the synchronized statement −

Syntax

synchronized(objectidentifier) {
// Access shared variables and other shared resources
}

Here, the objectidentifier is a reference to an object whose lock associates with


the monitor that the synchronized statement represents. Now we are going to see
two examples, where we will print a counter using two different threads. When
threads are not synchronized, they print counter value which is not in sequence, but
when we print counter by putting inside synchronized() block, then it prints
counter very much in sequence for both the threads.

Multithreading Example without Thread Synchronization


Here is a simple example which may or may not print counter value in sequence
and every time we run it, it produces a different result based on CPU availability to
a thread.

Example

Open Compiler
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() {


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");
}
}
}

This produces a different result every time you run this program −

Output
Starting Thread - 1
Starting Thread - 2
Counter --- 5
Counter --- 4
Counter --- 3
Counter --- 5
Counter --- 2
Counter --- 1
Counter --- 4
Thread Thread - 1 exiting.
Counter --- 3
Counter --- 2
Counter --- 1
Thread Thread - 2 exiting.

Multithreading Example with Thread Synchronization

Here is the same example which prints counter value in sequence and every time
we run it, it produces the same result.

Example

Open Compiler
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");
}
}
}

This produces the same result every time you run this program −

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.
Inter-thread Communication in Java
Inter-thread communication or Co-operation is all about allowing synchronized
threads to communicate with each other.

Cooperation (Inter-thread communication) is a mechanism in which a thread is


paused running in its critical section and another thread is allowed to enter (or
lock) in the same critical section to be executed. It is implemented by following
methods of Object class:

 wait()
 notify()
 notifyAll()

1) wait() method

The wait() method causes current thread to release the lock and wait until either
another thread invokes the notify() method or the notifyAll() method for this
object, or a specified amount of time has elapsed.

The current thread must own this object's monitor, so it must be called from the
synchronized method only otherwise it will throw exception.

Method Description
public final void wait()throws
It waits until object is notified.
InterruptedException
public final void wait(long timeout)throws It waits for the specified
InterruptedException amount of time.

2) notify() method

The notify() method wakes up a single thread that is waiting on this object's
monitor. If any threads are waiting on this object, one of them is chosen to be
awakened. The choice is arbitrary and occurs at the discretion of the
implementation.

Syntax:

1. public final void notify()


3) notifyAll() method

Wakes up all threads that are waiting on this object's monitor.

Syntax:

1. public final void notifyAll()

Understanding the process of inter-thread communication

The point to point explanation of the above diagram is as follows:

1. Threads enter to acquire lock.


2. Lock is acquired by on thread.
3. Now thread goes to waiting state if you call wait() method on the object.
Otherwise it releases the lock and exits.
4. If you call notify() or notifyAll() method, thread moves to the notified state
(runnable state).
5. Now thread is available to acquire lock.
6. After completion of the task, thread releases the lock and exits the monitor
state of the object.

Why wait(), notify() and notifyAll() methods are defined in Object class not
Thread class?

It is because they are related to lock and object has a lock.


Difference between wait and sleep?

Let's see the important differences between wait and sleep methods.

wait() sleep()
The sleep() method doesn't release the
The wait() method releases the lock.
lock.
It is a method of Object class It is a method of Thread class
It is the non-static method It is the static method
It should be notified by notify() or After the specified amount of time, sleep
notifyAll() methods is completed.

Example of Inter Thread Communication in Java

Let's see the simple example of inter thread communication.

Test.java

1. class Customer{
2. int amount=10000;
3.
4. synchronized void withdraw(int amount){
5. System.out.println("going to withdraw...");
6.
7. if(this.amount<amount){
8. System.out.println("Less balance; waiting for deposit...");
9. try{wait();}catch(Exception e){}
10.}
11.this.amount-=amount;
12.System.out.println("withdraw completed...");
13.}
14.
15.synchronized void deposit(int amount){
16.System.out.println("going to deposit...");
17.this.amount+=amount;
18.System.out.println("deposit completed... ");
19.notify();
20.}
21.}
22.
23.class Test{
24.public static void main(String args[]){
25.final Customer c=new Customer();
26.new Thread(){
27.public void run(){c.withdraw(15000);}
28.}.start();
29.new Thread(){
30.public void run(){c.deposit(10000);}
31.}.start();
32.
33.}}

Output:

going to withdraw...
Less balance; waiting for deposit...
going to deposit...
deposit completed...
withdraw completed

You might also like