AR20 JP Unit-4
AR20 JP Unit-4
Multitasking
Multitasking is a process of executing multiple tasks simultaneously. We use
multitasking to utilize the
CPU. Multitasking can be achieved by two ways:
1. Process-based Multitasking (Multiprocessing)
2. Thread-based Multitasking (Multithreading)
1) Process-based Multitasking (Multiprocessing)
Each process has its own address in memory i.e., each process allocates
separate memory area.
Process is heavyweight.
Cost of communication between the processes is high.
Switching from one process to another require some time for saving and
loading registers, memory maps, updating lists etc.
2) Thread-based Multitasking (Multithreading)
Threads share the same address space.
Thread is lightweight.
Cost of communication between the thread is low.
4.2 thread life cycle
Thread
A thread is a lightweight sub process, a 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 shares a common memory area.
Thread States
A thread can be in one of the five states. According to sun, there are only 4 states in
thread life cycle in java new, runnable, non-runnable and terminated. There is no
running state. But for better understanding the threads, we are explaining it in the 5
states.
The life cycle of the thread in java is controlled by JVM. The java thread states are as
follows:
1. New 4. Non-Runnable (Blocked)
2. Runnable 5. Terminated
3. Running
1) New
The thread is in new state if we create an instance of Thread class but before the invocation
of start () method.
A thread enters the newly created by using a new operator.
It is new state or born state immediately after creation. i.e. when a constructor is
called the Thread is created but is not yet to run() method will not begin until it
start() method is called.
After the start() method is called, the thread will go to the next state, Runnable
state.
2) Runnable
The thread is in runnable state after invocation of start () method, but the thread scheduler
has not selected it to be the running thread.
Once we invoke the start() method, the thread is runnable.
3) Running
The thread is in running state if the thread scheduler has selected it.
It is divided into two states:
The running states
• When the thread is running state, it assigned by CPU cycles and is actually running.
The Queued state.
• When the thread is in Queued state, it is waiting in the Queue and competing for its
turn to spend CPU cycles
• It is controlled by Virtual Machine Controller.
• When we use yield() method it makes sure other threads of the same priority have
chance to run.
• This method causes voluntary move itself to the queued state from the running state.
4) Non-Runnable (Blocked)
This is the state when the thread is still alive, but is currently not eligible to run.
The blocked state is entered when one of the following events occurs:
• The thread itself or another thread calls the suspend() method (it is deprecated)
• The thread calls an object’s wait() method
• The thread itself calls the sleep() method.
• The thread is waiting for some I/O operations to complete.
• The thread will join() another thread.
5) Terminated
A thread is in terminated or dead state when its run() method exits.
Starting a thread:
start() method of Thread class is used to start a newly created thread. It performs following
tasks:
A new thread starts (with new call stack).
The thread moves from new state to the Runnable state.
When the thread gets a chance to execute, its target run() method will run.
If we are not extending the Thread class, our class object would not be treated as a thread
object. So, we need to explicitly create Thread class object. We are passing the object of our
class that implements Runnable so that class run() method may execute.
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.
Synchronization
Synchronization is a process that involves coordinating the execution of multiple threads to
ensure a desired outcome without corrupting the shared data and preventing any occurrence
of deadlocks and race conditions.
Java Synchronization is better option where we want to allow only one thread to access the
shared resource.
The synchronization is mainly used to:
To prevent thread interference.
To prevent consistency problem.
Note: A race condition is an undesirable situation that occurs when a device or system
attempts to perform two or more operations at the same time, but because of the nature
of the device or system, the operations must be done in the proper sequence to be done
correctly.
All other threads attempting to enter the locked monitor will be suspended until the first
thread exits the monitor. These other threads are said to be waiting for the monitor. A thread
that owns a monitor can reenter the same monitor if it so desires.
Limitations
1. Concurrency Limitations: Java synchronization does not allow concurrent reads.
2. Decreases Efficiency: Java synchronized method run very slowly and can degrade
the performance,
Thread Synchronization
There are two types of thread synchronization
1. Mutual exclusive
2. Inter-thread communication.
Mutual Exclusive
Mutual Exclusive helps keep threads from interfering with one another while sharing data.
This can be done by two ways in java:
1. by synchronized method
2. by synchronized block
synchronized method
The synchronized keyword in java creates a block of code referred to as critical section. 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.
class Table
{
synchronized void printTable(int n) //synchronized method
{
for(int i=1;i<=10;i++)
{
System.out.println(n+"x"+i+"="+(n*i));
try
{
Thread.sleep(400);
}catch(InterruptedException e)
{
System.out.println(e);
}
}
}
}
class MyThread1 extends Thread
{
Table t;
MyThread1(Table t)
{
this.t=t;
}
public void run()
{
t.printTable(2);
}
}
class MyThread2 extends Thread
{
Table t;
MyThread2(Table t)
{
this.t=t;
}
public void run()
{
t.printTable(3);
}
}
synchronized (object)
{
//statement to be synchronized
}
Here, object is a reference to the object being synchronized. A synchronized block ensures
that a call to a synchronized method that is a member of object’s class occurs only after the
current thread has successfully entered object’s monitor.
Suppose you have 100 lines of code in your method, but you want to synchronize only 5
lines, you can use synchronized block. If you put all the codes of the method in the
synchronized block, it will work same as the synchronized method.
class Table
{
void printTable(int n)
{
for(int i=1;i<=10;i++)
{
System.out.println(n+"x"+i+"="+(n*i));
try
{
Thread.sleep(400);
}catch(InterruptedException e)
{
System.out.println(e);
}
}
}
}
Inter-thread communication
It is all about allowing synchronized threads to communicate with each other. 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:
1. wait()
2. notify()
3. notifyAll()
wait() method
It tells the calling thread to give up the monitor and go to sleep until some other thread enters
the same monitor and calls notify( ) or notifyAll( ), 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. Its general form is:
Method Description
public final void wait()throws InterruptedException waits until object is notified.
public final void wait(long timeout)throws waits for the specified amount of
InterruptedException time.
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.
Its general form is:
public final void notify( )
notifyAll( ) method
It wakes up all the threads that called wait( ) on the same object. One of the threads
will be granted access. Its general form is:
public final void notifyAll( )
In java language we are transferring the data in the form of two ways: -
1. Byte format 2. Character format
Stream/channel: -
Types of Streams
In general, streams are classified into two types known as character streams and the byte
streams. The java.io package provides two sets of class hierarchies to handle character and
byte streams for reading and writing:
1. Input Stream and Output Stream classes are operated on bytes for reading and writing,
respectively.
2. Reader and Writer classes are operated on characters for reading and writing,
respectively.
3. There are two other classes that are useful for handling input and output. These are
File class and Random-Access File class.
The java.io package contains a large number of stream classes that provide capabilities for
processing all types of data. These classes may be categorized into two groups based on the
data type on which they operate.
1. Byte oriented streams. (Supports byte formatted data to transfer)
2. Character oriented stream. (Supports character formatted data to transfer)
Byte oriented streams: -
Java.io.FileInputStream
To read the data from the destination file to the java application we have to use FileInputSream
class.
It’s an abstract class.
It is a superclass of all binary stream representing inputs.
It gets the input data from data source and gives to the program.
A data source can be a file, a string, or memory – anything that can contain data.
To read the data from the .txt file we have to read() method.
public abstract int read() throws IOException
public int read(byte[] b) throws IOException
public int read(byte[] b, int off, int len) throws IOException
public long skip(long n) throws IOException
public int available() throws IOException
public void close() throws IOException
public void mark(int readlimit)
public void reset() throw IOException
public boolean markSupported()
Java.io.FileOutputStream: -
To write the data to the destination file we have to use the FileOutputStream.
It’s an abstract class.
It is a superclass of all binary stream representing outputs.
It accepts output bytes and sends them to the data sink.
A data sink can be a file, a string, or memory – anything that can contain data.
It inherits Flushable interface.
To write the data to the destination file we have to use write() method.
public void write(int) throws IOException
public void write(byte[]) throws IOException
public void write(byte[], int offser, int len) throws IOException
public void flush()throws IOException
public void close() throws IOException
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
//import java.io.*;
class InputStreamOutputStreamDemo{
public static void main(String [] args){
try{
File f = new File("D://Test//WelcomeScan.webp");
//create inputstream WelcomeScan
FileInputStream input = new FileInputStream(f);
byte b[] = new byte[(int)f.length()];
int numBytes = input.read(b);
System.out.println("Data from File Read Successfully...");
Writer
It is an abstract class for writing to character streams.
The methods that a subclass must implement are write(char[], int, int), flush(), and
close().
Most subclasses will override some of the methods defined here to provide higher
efficiency, functionality or both.
Constructor
Constructor Description
Writer() It creates a new character-stream writer whose critical
sections will synchronize on the writer itself.
Writer(Object lock) It creates a new character-stream writer whose critical
sections will synchronize on the given object.
Methods
Method Description
Writer append(char c) It appends the specified character to this writer.
Writer append(CharSequence csq) It appends the specified character sequence to this
writer
Writer append(CharSequence csq, It appends a subsequence of the specified character
int start, int end) sequence to this writer
abstract void close() It closes the stream, flushing it first.
abstract void flush() It flushes the stream.
void write(char[] cbuf) It writes an array of characters.
abstract void write(char[] cbuf, int It writes a portion of an array of characters.
off, int len)
void write(int c) It writes a single character
void write(String str) It writes a string.
void write(String str, int off, int len) It writes a portion of a string.
Reader
Java Reader is an abstract class for reading character streams.
The only methods that a subclass must implement are read(char[], int, int) and close().
Most subclasses, however, will override some of the methods to provide higher
efficiency, additional functionality, or both.
Some of the implementation classes are BufferedReader, CharArrayReader, FilterReader,
InputStreamReader, PipedReader, StringReader
Constructor
Constructor Description
protected Reader() It creates a new character-stream reader whose critical
sections will synchronize on the reader itself.
protected Reader(Object lock) It creates a new character-stream reader whose critical
sections will synchronize on the given object.
Methods:
Method Description
abstract void close() It closes the stream and releases any system
resources associated with it.
void mark(int readAheadLimit) It marks the present position in the stream.
boolean markSupported() It tells whether this stream supports the mark()
operation.
int read() It reads a single character.
int read(char[] cbuf) It reads characters into an array.
abstract int read(char[] cbuf, int off, int It reads characters into a portion of an array.
len)
int read(CharBuffer target) It attempts to read characters into the specified
character buffer.
boolean ready() It tells whether this stream is ready to be read.
void reset() It resets the stream.
long skip(long n) It skips characters.
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
class FileReaderFileWriterDemo{
public static void main(String [] args){
FileReader fin;
FileWriter fout;
int c;
if(args.length != 2){
System.out.println("Please Provide 2 File Names");
return;
}
try{
fin = new FileReader(args[0]);
fout = new FileWriter(args[1]);
do{
c = fin.read();
if (c != -1)
fout.write(c);
}while(c != -1);
RandomAccessFile works with file as large array of bytes stored in the file system and a cursor
using which we can move the file pointer position.
RandomAccessFile class is part of Java IO. While creating the instance of RandomAccessFile in
java, we need to provide the mode to open the file. For example, to open the file for read only
mode we have to use “r” and for read-write operations we have to use “rw”.
Using file pointer, we can read or write data from random access file at any position. To get the
current file pointer, you can call getFilePointer () method and to set the file pointer index, you
can call seek (int i) method.
If we write data at any index where data is already present, it will override it.
In first line, we are creating RandomAccessFile instance for file in read-only mode.
In second line, we are moving the file pointer to index 1.
We have created byte array of length 5, so when we are calling read(bytes) method then 5
bytes are read from file to the byte array.
Finally, we are closing the RandomAccessFile resource and printing the byte array to console.
Since RandomAccessFile treats file as byte array, write operation can override the data as well
as it can append to a file. It all depends on the file pointer position. If the pointer is moved
beyond the file length and then write operation is called, then there will be junk data written in
the file. So, you should take care of this while using write operation.
class RandomAccessDemo{
public static void main(String [] args){
try{
String filePath = args[0];
RandomAccessFile rafile = new RandomAccessFile(filePath,"rw");
byte [] data = new byte[(int) rafile.length()];
rafile.read(data);
rafile.seek(rafile.length());
rafile.write("This is the content written from the program\n".getBytes());
rafile.write("I Want to append the content".getBytes());
rafile.seek(0);
/*rafile.seek(0);
rafile.write("This is the content written from the program\n".getBytes());
rafile.write("I Want to change the content".getBytes());
rafile.seek(0);
}
catch(IOException ioe){
ioe.printStackTrace();
}
}
}
Collections:
A Collection is a group of individual objects represented as a single unit. Java provides Collection
Framework which defines several classes and interfaces to represent a group of objects as a
single unit.
The Collection in Java is a framework that provides an architecture to store and manipulate
the group of objects.
All the operations that you perform on a data such as searching, sorting, insertion, manipulation,
deletion, etc. can be achieved by Java Collections.
Java Collection means a single unit of objects. Java Collection framework provides many
interfaces (Set, List, Queue, Deque, etc.) and classes (ArrayList, Vector, LinkedList, PriorityQueue,
HashSet, LinkedHashSet, TreeSet, etc.).
The Collection interface (java.util.Collection) and Map interface (java.util.Map) are the two main
“root” interfaces of Java collection classes.
Accessing elements of these Data Structures was a hassle as each had a different method (and
syntax) for accessing its members.
2. Reduces programming effort: A programmer doesn’t have to worry about the design
of Collection, and he can focus on its best use in his program.
2. Set: Doesn't allow duplicates. Example implementations of Set interface are HashSet
(Hashing based) and TreeSet (balanced BST based). Note that TreeSet implements
SortedSet.
3. List: Can contain duplicates and elements are ordered. Example implementations are
LinkedList (linked list based) and ArrayList (dynamic array based)
4. Queue: Typically order elements in FIFO order except exceptions like PriorityQueue.
Deque: Elements can be inserted and removed at both ends. Allows
both LIFO and FIFO.
5. Map: Contains Key value pairs. Doesn't allow duplicates. Example implementation are
HashMap and TreeMap.TreeMap implements SortedMap.
The difference between Set and Map interface is that in Set we have only keys, whereas in Map,
we have key, value pairs.
Java ArrayList class
Java ArrayList class uses a dynamic array for storing the elements. It inherits AbstractList
class and implements List interface.
The important points about Java ArrayList class are:
Java new generic collection allows you to have only one type of object in collection. Now it
is type safe so typecasting is not required at run time.
In generic collection, we specify the type in angular braces. Now ArrayList is forced to have
only specified type of objects in it. If you try to add another type of object, it gives compile
time error.
import java.util.*;
class TestCollection1{
public static void main(String args[]){
ArrayList<String> list=new ArrayList<String>();//Creating arraylist
list.add("Ravi");//Adding object in arraylist
list.add("Vijay");
list.add("Ravi");
list.add("Ajay");
//Traversing list through Iterator
Iterator itr=list.iterator();
while(itr.hasNext()){
System.out.println(itr.next());
}
}
}
Java LinkedList class uses doubly linked list to store the elements. It provides a linked-list
data structure. It inherits the AbstractList class and implements List and Deque interfaces.
ArrayList LinkedList
ArrayList internally uses dynamic array to LinkedList internally uses doubly linked list to
store the elements. store the elements.
Manipulation with ArrayList is slow because it Manipulation with LinkedList is faster than
internally uses array. If any element is ArrayList because it uses doubly linked list so
removed from the array, all the bits are no bit shifting is required in memory.
shifted in memory.
ArrayList class can act as a list only because it LinkedList class can act as a list and
implements List only. queue both because it implements List
and Deque interfaces.
ArrayList is better for storing and accessing LinkedList is better for manipulating data.
data.
System.out.println("arraylist: "+al);
System.out.println("linkedlist: "+al2);
}
}
Set:
Set is a collection that does not contain duplicates. Set collection in java.util models the
mathematical concept set. The concepts of union, intersection, and the difference of a set are
available in the Set interface and supported by its subclasses. We will discuss two classes under
this interface, i.e., HashSet and TreeSet. TreeSet is a sorted collection as it inherits the SortedSet
interface (sub-interface of Set), whereas HashSet is not a sorted collection. HashSet uses the
concept of hashing.
Java HashSet class is used to create a collection that uses a hash table for storage. It inherits
the AbstractSet class and implements Set interface.
import java.util.*;
class TestCollection9{
public static void main(String args[]){
//Creating HashSet and adding elements
HashSet<String> set=new HashSet<String>();
set.add("Ravi");
set.add("Vijay");
set.add("Ravi");
set.add("Ajay");
//Traversing elements
Iterator<String> itr=set.iterator();
while(itr.hasNext()){
System.out.println(itr.next());
}
}
}
Java LinkedHashSet class
Java LinkedHashSet class is a Hash table and Linked list implementation of the set interface.
It inherits HashSet class and implements Set interface.
Java TreeSet class implements the Set interface that uses a tree for storage. It inherits
AbstractSet class and implements NavigableSet interface. The objects of TreeSet class are
stored in ascending order.
The important points about Java TreeSet class are:
Contains unique elements only like HashSet.
Access and retrieval times are quiet fast.
Maintains ascending order.
Queue;
Java Queue Interface
Java Queue interface orders the element in FIFO(First In First Out) manner. In FIFO, first
element is removed first and last element is removed at last
PriorityQueue class
The PriorityQueue class provides the facility of using queue. But it does not orders the
elements in FIFO manner. It inherits AbstractQueue class.
PriorityQueue class declaration
Let's see the declaration for java.util.PriorityQueue class.
1. public class PriorityQueue<E> extends AbstractQueue<E> implements Serializable
ArrayDeque class
The ArrayDeque class provides the facility of using deque and resizable-array. It inherits
AbstractCollection class and implements the Deque interface.
Map is useful if you have to search, update or delete elements on the basis of key.
There are two interfaces for implementing Map in java: Map and SortedMap, and three
classes: HashMap, LinkedHashMap and TreeMap. The hierarchy of Java Map is given
below:
Map doesn't allow duplicate keys, but you can have duplicate values. HashMap and
LinkedHashMap allows null keys and values but TreeMap doesn't allow any null key or
value.
Map can't be traversed so you need to convert it into Set using keySet() or entrySet() method.
Class Description
HashMap HashMap is the implementation of Map but it doesn't maintain any order.
LinkedHashMap LinkedHashMap is the implementation of Map, it inherits HashMap class. It
maintains insertion order.
TreeMap TreeMap is the implementation of Map and SortedMap, it maintains
ascending order.
Map.Entry Interface
Entry is the sub interface of Map. So, we will be accessed it by Map. Entry name. It provides
methods to get key and value.
Java HashMap class implements the map interface by using a hashtable. It inherits
AbstractMap class and implements Map interface.
Java TreeMap class implements the Map interface by using a tree. It provides an efficient
means of storing key/value pairs in sorted order.
import java.util.*;
public class TreeMapExample {
public static void main(String args[]) {
// Create and populate tree map
Map<Integer, String> map = new TreeMap<Integer, String>();
map.put(102,"Let us C");
map.put(103, "Operating System");
map.put(101, "Data Communication and Networking");
System.out.println("Values before remove: "+ map);
// Remove value for key 102
map.remove(102);
System.out.println("Values after remove: "+ map);
}
}
Iterator interface
Iterator interface provides the facility of iterating the elements in a forward direction only.
There are only three methods in the Iterator interface. They are:
Method Description
public boolean It returns true if the iterator has more elements otherwise it returns
hasNext() false.
public Object next() It returns the element and moves the cursor pointer to the next
element.
public void remove() It removes the last elements returned by the iterator. It is less used.
Iterable Interface
The Iterable interface is the root interface for all the collection classes. The Collection interface
extends the Iterable interface and therefore all the subclasses of Collection interface also
implement the Iterable interface.
Iterable Iterator
Iterable is an interface Iterator is an interface
Belongs to java.lang.package Belongs to java.util package
Provides one single abstract method called Provides tow abstract methods called
iterator() hasNext() and next()
It is a representatation of a series of elements It represents the object with iteration state.
that can be traversed