You are on page 1of 41

Unit-4: IO and Multi Threading

 Java I/O (Input and Output) is used to process the input and produce the output
based on the input.
 Java uses the concept of 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 IO API.

java.io Package
 Java.io package provides classes for system input and output through data
streams, serialization and the file system.

 The java.io package contains nearly every class you might ever need to perform
input and output (I/O) in Java.

 The InputStream class provides many different subclasses to read different kind
of input data from a source and the OutputStream class provides many different
subclasses to write different kind of output to a destination.

 Java provides strong but flexible support for I/O related to Files and networks.

Stream
 A stream is a sequence of data.In Java a stream is composed of bytes. It's called
a stream because it's like a stream of water that continues to flow.
 In java, 3 streams are created for us automatically. All these streams are attached
with 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 error message to the console.
System.out.println("simple message");
System.err.println("error message");

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


int i=System.in.read();//returns ASCII code of 1st character
System.out.println((char)i);//will print the character

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

Commonly used methods of OutputStream class


Method Description
1) public void write(int)throws is used to write a byte to the current
IOException: output 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
IOException: stream.
 InputStream class
 InputStream class is an abstract class.It is the superclass of all classes
representing an input stream of bytes.

Commonly used methods of InputStream class


Method Description
1) public abstract int reads the next byte of data from the input
read()throws IOException: stream.It returns -1 at the end of file.
2) public int returns an estimate of the number of bytes that
available()throws can be read from the current input stream.
IOException:
3) public void close()throws is used to close the current input stream.
IOException:

Byte Streams
 Java byte streams are used to perform input and output of 8-bit bytes. Though
there are many classes related to byte streams but the most frequently used
classes are ,FileInputStream and FileOutputStream.
 Following is an example which makes use of these two classes to copy an input
file into an output file:
import java.io.*;

public class CopyFile {


public static void main(String args[]) throws IOException
{
FileInputStream in = null;
FileOutputStream out = null;
try {
in = new FileInputStream("input.txt");
out = new FileOutputStream("output.txt");

int c;
while ((c = in.read()) != -1) {
out.write(c);
}
}finally {
if (in != null) {
in.close();
}
if (out != null) {
out.close();
}
}
}
}
 Now let's have a file input.txt with the following content:
This is test for copy file.

 As a next step, compile above program and execute it, which will result in
creating output.txt file with the same content as we have in input.txt. So
let's put above code in CopyFile.java file and do the following:
$javac CopyFile.java
$java CopyFile

Character Streams

 Java Character streams are used to perform input and output for 16-bit
unicode. Though there are many classes related to character streams but the
most frequently used classes are ,FileReader and FileWriter.

 Though internally FileReader uses FileInputStream and FileWriter uses


FileOutputStream but here major difference is that FileReader reads two bytes
at a time and FileWriter writes two bytes at a time.

 We can re-write above example which makes use of these two classes to copy an
input file (having unicode characters) into an output file:
import java.io.*;

public class CopyFile {


public static void main(String args[]) throws IOException
{
FileReader in = null;
FileWriter out = null;
try {
in = new FileReader("input.txt");
out = new FileWriter("output.txt");

int c;
while ((c = in.read()) != -1) {
out.write(c);
}
}finally {
if (in != null) {
in.close();
}
if (out != null) {
out.close();
}
}
}
}
 Now let's have a file input.txt with the following content:
This is test for copy file.
 As a next step, compile above program and execute it, which will result in
creating output.txt file with the same content as we have in input.txt. So
let's put above code in CopyFile.java file and do the following:
$javac CopyFile.java
$java CopyFile

Standard Streams
 All the programming languages provide support for standard I/O where user's
program can take input from a keyboard and then produce output on the
computer screen.
 If you are aware if C or C++ programming languages, then you must be aware of
three standard devices STDIN, STDOUT and STDERR. Similar way Java provides
following three standard streams
 Standard Input: This is used to feed the data to user's program and usually a
keyboard is used as standard input stream and represented as System.in.
 Standard Output: This is used to output the data produced by the user's
program and usually a computer screen is used to standard output stream and
represented as System.out.
 Standard Error: This is used to output the error data produced by the user's
program and usually a computer screen is used to standard error stream and
represented as System.err.

 Following is a simple program which creates InputStreamReader to read


standard input stream until the user types a "q":
import java.io.*;
public class ReadConsole {
public static void main(String args[]) throws IOException
{
InputStreamReader cin = null;

try {
cin = new InputStreamReader(System.in);
System.out.println("Enter characters, 'q' to quit.");
char c;
do {
c = (char) cin.read();
System.out.print(c);
} while(c != 'q');
}finally {
if (cin != null) {
cin.close();
}
}
}
}
 This program continues reading and outputting same character until we press
'q':
$javac ReadConsole.java
$java ReadConsole
Enter characters, 'q' to quit.
1
1
e
e
q
q

File Class
Reading and Writing Files:

 For handling files in java, the two important streams


are FileInputStream and FileOutputStream

 FileInputStream:
 This stream is used for reading data from the files. Objects can be created
using the keyword new and there are several types of constructors
available.
 Following constructor takes a file name as a string to create an input
stream object to read the file.:
InputStream f = new FileInputStream("C:/java/hello");
 Following constructor takes a file object to create an input stream object
to read the file. First we create a file object using File() method as follows:
File f = new File("C:/java/hello");
InputStream f = new FileInputStream(f);

 Methods of InputStream:
SN Methods with Description

1 public void close() throws IOException{}


This method closes the file output stream. Releases any system resources
associated with the file. Throws an IOException

2 protected void finalize()throws IOException {}


This method cleans up the connection to the file. Ensures that the close
method of this file output stream is called when there are no more references
to this stream. Throws an IOException.

3 public int read(int r)throws IOException{}


This method reads the specified byte of data from the InputStream. Returns
an int. Returns the next byte of data and -1 will be returned if it's end of file.

4 public int read(byte[] r) throws IOException{}


This method reads r.length bytes from the input stream into an array.
Returns the total number of bytes read. If end of file -1 will be returned.

5 public int available() throws IOException{}


Gives the number of bytes that can be read from this file input stream.
Returns an int.

FileOutputStream:

 FileOutputStream is used to create a file and write data into it. The stream would
create a file, if it doesn't already exist, before opening it for output.

 Following constructor takes a file name as a string to create an input stream


object to write the file:
OutputStream f = new FileOutputStream("C:/java/hello")
 Following constructor takes a file object to create an output stream object to
write the file. First, we create a file object using File() method as follows:
File f = new File("C:/java/hello");
OutputStream f = new FileOutputStream(f);
 Once you have OutputStream object in hand, then there is a list of helper
methods, which can be used to write to stream or to do other operations on the
stream.
SN Methods with Description
1 public void close() throws IOException{}
This method closes the file output stream. Releases any system resources
associated with the file. Throws an IOException

2 protected void finalize()throws IOException {}


This method cleans up the connection to the file. Ensures that the close
method of this file output stream is called when there are no more references
to this stream. Throws an IOException.

3 public void write(int w)throws IOException{}


This methods writes the specified byte to the output stream.

4 public void write(byte[] w)


Writes w.length bytes from the mentioned byte array to the OutputStream.

 Following is the example to demonstrate InputStream and OutputStream:


import java.io.*;

public class fileStreamTest{

public static void main(String args[]){

try{
byte bWrite [] = {11,21,3,40,5};
OutputStream os = new FileOutputStream("test.txt");
for(int x=0; x < bWrite.length ; x++){
os.write( bWrite[x] ); // writes the bytes
}
os.close();

InputStream is = new FileInputStream("test.txt");


int size = is.available();

for(int i=0; i< size; i++){


System.out.print((char)is.read() + " ");
}
is.close();
}catch(IOException e){
System.out.print("Exception");
}
}
}

 The above code would create file test.txt and would write given numbers in binary
format. Same would be output on the stdout screen.
Example of Reading the data of current java file and writing it into another file
 We can read the data of any file using the FileInputStream class whether
it is java file, image file, video file etc. In this example, we are reading the
data of C.java file and writing it into another file M.java.
import java.io.*;
class C{
public static void main(String args[])throws Exception{
FileInputStream fin=new FileInputStream("C.java");

FileOutputStream fout=new FileOutputStream("M.java");

int i=0;

while((i=fin.read())!=-1){
fout.write((byte)i);
}
fin.close();
}
}

 Java FileWriter and FileReader (File Handling in java)

Java FileWriter class

 Java FileWriter class is used to write character-oriented data to the file.


 Constructors of FileWriter class
Constructor Description
FileWriter(String file) creates a new file. It gets file name in
string.
FileWriter(File file) creates a new file. It gets file name in File
object.

 Methods of FileWriter class


Method Description
1) public void write(String text) writes the string into FileWriter.
2) public void write(char c) writes the char into FileWriter.
3) public void write(char[] c) writes char array into FileWriter.
4) public void flush() flushes the data of FileWriter.
5) public void close() closes FileWriter.

 Java FileWriter Example


In this example, we are writing the data in the file abc.txt.
import java.io.*;
class Simple{
public static void main(String args[]){
try{
FileWriter fw=new FileWriter("abc.txt");
fw.write("my name is sachin");
fw.close();
}catch(Exception e){System.out.println(e);}
System.out.println("success");
}
}
Output:
success...

Java FileReader class


 Java FileReader class is used to read data from the file. It returns data in byte
format like FileInputStream class.
 Constructors of FileWriter class
Constructor Description
FileReader(String It gets filename in string. It opens the given file in read
file) mode. If file doesn't exist, it throws
FileNotFoundException.
FileReader(File It gets filename in file instance. It opens the given file in
file) read mode. If file doesn't exist, it throws
FileNotFoundException.

 Methods of FileReader class


Method Description
1) public int read() returns a character in ASCII form. It returns -1 at
the end of file.
2) public void close() closes FileReader.
 Java FileReader Example
In this example, we are reading the data from the file abc.txt file.
import java.io.*;
class Simple{
public static void main(String args[])throws Exception{
FileReader fr=new FileReader("abc.txt");
int i;
while((i=fr.read())!=-1)
System.out.println((char)i);
fr.close();
}
}
Output: my name is sachin

Directories in Java:
A directory is a File which can contains a list of other files and directories. You
use File object to create directories, to list down files available in a directory.

 Creating Directories:
 There are two useful File utility methods, which can be used to create
directories:
 The mkdir( ) method creates a directory, returning true on success and
false on failure. Failure indicates that the path specified in the File
object already exists, or that the directory cannot be created because
the entire path does not exist yet.
 The mkdirs() method creates both a directory and all the parents of the
directory.

 Following example creates "/tmp/user/java/bin" directory:


import java.io.File;

public class CreateDir {


public static void main(String args[]) {
String dirname = "/tmp/user/java/bin";
File d = new File(dirname);
// Create directory now.
d.mkdirs();
}
}
 Compile and execute above code to create "/tmp/user/java/bin".

Note: Java automatically takes care of path separators on UNIX and


Windows as per conventions. If you use a forward slash (/) on a Windows
version of Java, the path will still resolve correctly.

 Listing Directories:

 You can use list( ) method provided by File object to list down all the files
and directories available in a directory as follows:
import java.io.File;

public class ReadDir {


public static void main(String[] args) {

File file = null;


String[] paths;

try{
// create new file object
file = new File("/tmp");

// array of files and directory


paths = file.list();

// for each name in the path array


for(String path:paths)
{
// prints filename and directory name
System.out.println(path);
}
}catch(Exception e){
// if any error occurs
e.printStackTrace();
}
}
}
 This would produce following result based on the directories and files
available in your/tmp directory:
test1.txt
test2.txt
ReadDir.java
ReadDir.class

Java Scanner class


 There are various ways to read input from the keyboard, the
java.util.Scanner class is one of them.
 The Java Scanner class breaks the input into tokens using a
delimiter that is whitespace bydefault. It provides many methods to read
and parse various primitive values.
 Java Scanner class is widely used to parse text for string and primitive
types using regular expression.

 Commonly used methods of Scanner class


There is a list of commonly used Scanner class methods:
Method Description
public String next() it returns the next token from the scanner.
public String nextLine() it moves the scanner position to the next line and
returns the value as a string.
public byte nextByte() it scans the next token as a byte.
public short nextShort() it scans the next token as a short value.
public int nextInt() it scans the next token as an int value.
public long nextLong() it scans the next token as a long value.
public float nextFloat() it scans the next token as a float value.
public double nextDouble() it scans the next token as a double value.

 Java Scanner Example to get input from console


import java.util.Scanner;
class ScannerTest{
public static void main(String args[]){
Scanner sc=new Scanner(System.in);

System.out.println("Enter your rollno");


int rollno=sc.nextInt();
System.out.println("Enter your name");
String name=sc.next();
System.out.println("Enter your fee");
double fee=sc.nextDouble();
System.out.println("Rollno:"+rollno+" name:"+name+" fee:"+fee);
sc.close();
}
}
 Java Scanner Example with delimiter
Let's see the example of Scanner class with delimiter. The \s represents
whitespace.
import java.util.*;
public class ScannerTest2{
public static void main(String args[]){
String input = "10 tea 20 coffee 30 tea buiscuits";
Scanner s = new Scanner(input).useDelimiter("\\s");
System.out.println(s.nextInt());
System.out.println(s.next());
System.out.println(s.nextInt());
System.out.println(s.next());
s.close();
}
}
Output: Java.io.PrintWriter Class

PrintWriter Class

 The Java.io.PrintWriter class prints formatted representations of objects to a


text-output stream.
 Following is the declaration for Java.io.PrintWriter class:
public class PrintWriter
extends Writer
 Following are the fields for Java.io.PrintWriter class:
 protected Writer out -- This is the character-output stream of this
PrintWriter.
 protected Object lock -- This is the object used to synchronize
operations on this stream.

 Class constructors
S.N. Constructor & Description

1 PrintWriter(File file)
This creates a new PrintWriter, without automatic line flushing, with
the specified file.

2 PrintWriter(File file, String csn)


This creates a new PrintWriter, without automatic line flushing, with
the specified file and charset.

3 PrintWriter(OutputStream out)
This creates a new PrintWriter, without automatic line flushing, from
an existing OutputStream.

4 PrintWriter(OutputStream out, boolean autoFlush)


This creates a new PrintWriter from an existing OutputStream.
5 PrintWriter(String fileName)
This creates a new PrintWriter, without automatic line flushing, with
the specified file name.

6 PrintWriter(String fileName, String csn)


This creates a new PrintWriter, without automatic line flushing, with
the specified file name and charset.

7 PrintWriter(Writer out)
This creates a new PrintWriter, without automatic line flushing.

8 PrintWriter(Writer out, boolean autoFlush)


This creates a new PrintWriter.

 Class methods
S.N. Method & Description

1 PrintWriter append(char c)
This method appends the specified character to this writer.

2 PrintWriter append(CharSequence csq)


This method appends the specified character sequence to this writer.

3 PrintWriter append(CharSequence csq, int start, int end)


This method appends a subsequence of the specified character sequence to
this writer.

4 boolean checkError()
This method flushes the stream if it's not closed and checks its error state.

5 protected void clearError()


This method Clears the error state of this stream.

6 void close()
This method Closes the stream and releases any system resources
associated with it.

7 void flush()
This method Flushes the stream.

8 PrintWriter format(Locale l, String format, Object... args)


This method writes a formatted string to this writer using the specified
format string and arguments.

9 PrintWriter format(String format, Object... args)


This method writes a formatted string to this writer using the specified
format string and arguments.
10 void print(boolean b)
This method prints a boolean value.

11 void print(char c)
This method prints a character.

12 void print(char[] s)
This method Prints an array of characters.

13 void print(double d)
This method Prints a double-precision floating-point number.

14 void print(float f)
This method prints a floating-point number.

15 void print(int i)
This method prints an integer.

16 void print(long l)
This method prints a long integer.

17 void print(Object obj)


This method prints an object.

18 void print(String s)
This method prints a string.

19 PrintWriter printf(Locale l, String format, Object... args)


This is a convenience method to write a formatted string to this writer using
the specified format string and arguments.

20 PrintWriter printf(String format, Object... args)


This is a convenience method to write a formatted string to this writer using
the specified format string and arguments.

21 void println()
This method terminates the current line by writing the line separator string.

22 void println(boolean x)
This method prints a boolean value and then terminates the line.

23 void println(char x)
This method prints a character and then terminates the line.

24 void println(char[] x)
This method prints an array of characters and then terminates the line.

25 void println(double x)
This method prints a double-precision floating-point number and then
terminates the line.

26 void println(float x)
This method prints a floating-point number and then terminates the line.

27 void println(int x)
This method prints an integer and then terminates the line.

28 void println(long x)
This method prints a long integer and then terminates the line.

29 void println(Object x)
This method prints an Object and then terminates the line.

30 void println(String x)
This method prints a String and then terminates the line.

31 protected void setError()


This method indicates that an error has occurred.

32 void write(char[] buf)


This method writes an array of characters.

33 void write(char[] buf, int off, int len)


This method writes a portion of an array of characters.

34 void write(int c)
This methodWrites a single character.

35 void write(String s)
This method writes a string.

36 void write(String s, int off, int len)


This method writes a portion of a string.

Transient vs Volatile modifiers in Java


 Java defines two interesting type modifiers: transient and volatile.

 These modifiers are used to handle somewhat specialized situations.

 When an instance variable is declared as transient, then its value need not
persist when an object is stored. For example:
Class T {
transient int a; //will not persist
int b; //will persist
}
 Here, if an object of type T is written to a persistent storage area, the contents
of a would not be saved, but the contents of b would.

 The volatile modifier tells the compiler that the variable modified
by volatile can be changed unexpectedly by other parts of your program.

 One of these situations involves multithreaded programs. In a multithreaded


program, sometimes, two or more threads share the same instance variable.

RandomAccessFile
 The RandomAccessFile class in the Java IO API allows you to move around a file
and read from it or write to it as you need.
 You can replace existing parts of a file too. This is not possible with
the FileInputStream or FileOutputStream.

 Creating a RandomAccessFile
 Before you can work with the RandomAccessFile class you must
instantiate it. Here is how that looks:
RandomAccessFile file =
new RandomAccessFile("c:\\data\\file.txt", "rw");

 Notice the second input parameter to the constructor: "rw". This is the
mode you want to open file in. "rw" means read/write mode. Check the
JavaDoc for more details about what modes you can open
aRandomAccessFile in.

 Moving Around a RandomAccessFile


 To read or write at a specific location in a RandomAccessFile, you must
first position the file pointer at the location to read or write. This is done
using the seek() method.
 The current position of the file pointer can be obtained by calling
the getFilePointer() method.
Here is a simple example:
RandomAccessFile file =
new RandomAccessFile("c:\\data\\file.txt", "rw");
file.seek(200);
long pointer = file.getFilePointer();
file.close();

 Reading from a RandomAccessFile

 Reading from a RandomAccessFile is done using one of its


many read() methods. Here is a simple example:
RandomAccessFile file =
new RandomAccessFile("c:\\data\\file.txt", "rw");
int aByte = file.read();
file.close();

 The read() method reads the byte located a the position in the file currently
pointed to by the file pointer.

 Here is a thing the JavaDoc forgets to mention: The read() method


increments the file pointer to point to the next byte in the file after the byte
just read! This means that you can continue to call read() without having
to manually move the file pointer.

 Writing to a RandomAccessFile
 Writing to a RandomAccessFile can be done using one it its
many write() methods. Here is a simple example:
RandomAccessFile file = new RandomAccessFile("c:\\data\\file.txt",
"rw");

file.write("Hello World".getBytes());

file.close();

 Just like with the read() method the write() method advances the file
pointer after being called. That way you don't have to constantly move the
file pointer to write data to a new location in the file.

 RandomAccessFile Class Methods:


S.N. Method & Description

1 void close()
This method Closes this random access file stream and releases any system
resources associated with the stream.

2 FileChannel getChannel()
This method returns the unique FileChannel object associated with this file.

3 FileDescriptor getFD()
This method returns the opaque file descriptor object associated with this
stream.

4 long getFilePointer()
This method returns the current offset in this file.

5 long length()
This method returns the length of this file.

6 int read()
This method reads a byte of data from this file.

7 int read(byte[] b)
This method reads up to b.length bytes of data from this file into an array
of bytes.

8 int read(byte[] b, int off, int len)


This method reads up to len bytes of data from this file into an array of
bytes.

9 boolean readBoolean()
This method reads a boolean from this file.

10 byte readByte()
This method reads a signed eight-bit value from this file.

11 char readChar()
This method reads a character from this file.

12 double readDouble()
This method reads a double from this file.

13 float readFloat()
This method reads a float from this file.

14 void readFully(byte[] b)
This method reads b.length bytes from this file into the byte array, starting
at the current file pointer.

15 void readFully(byte[] b, int off, int len)


This method reads exactly len bytes from this file into the byte array,
starting at the current file pointer.

16 int readInt()
This method reads a signed 32-bit integer from this file.

17 String readLine()
This method reads the next line of text from this file.

18 long readLong()
This method reads a signed 64-bit integer from this file.

19 short readShort()
This method reads a signed 16-bit number from this file.

20 int readUnsignedByte()
This method reads an unsigned eight-bit number from this file.

21 int readUnsignedShort()
This method reads an unsigned 16-bit number from this file.

22 String readUTF()
This method reads in a string from this file.

23 void seek(long pos)


This method sets the file-pointer offset, measured from the beginning of this
file, at which the next read or write occurs.

24 void setLength(long newLength)


This method sets the length of this file.

25 int skipBytes(int n)
This method attempts to skip over n bytes of input discarding the skipped
bytes.

26 void write(byte[] b)
This method writes b.length bytes from the specified byte array to this file,
starting at the current file pointer.

27 void write(byte[] b, int off, int len)


This method writes len bytes from the specified byte array starting at offset
off to this file.

28 void write(int b)
This method writes the specified byte to this file.

29 void writeBoolean(boolean v)
This method writes a boolean to the file as a one-byte value.

30 void writeByte(int v)
This method writes a byte to the file as a one-byte value.

31 void writeBytes(String s)
This method writes the string to the file as a sequence of bytes.

32 void writeChar(int v)
This method writes a char to the file as a two-byte value, high byte first.

33 void writeChars(String s)
This method writes a string to the file as a sequence of characters.

34 void writeDouble(double v)
This method converts the double argument to a long using the
doubleToLongBits method in class Double, and then writes that long value
to the file as an eight-byte quantity, high byte first.

35 void writeFloat(float v)
This method converts the float argument to an int using the floatToIntBits
method in class Float, and then writes that int value to the file as a four-
byte quantity, high byte first.

36 void writeInt(int v)
This method writes an int to the file as four bytes, high byte first.

37 void writeLong(long v)
This method writes a long to the file as eight bytes, high byte first.

38 void writeShort(int v)
This method writes a short to the file as two bytes, high byte first.

39 void writeUTF(String str)


This method writes a string to the file using modified UTF-8 encoding in a
machine-independent manner.

+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Introduction to MultiThreading
 Java provides built-in support for multithreaded programming. A multithreaded
program contains two or more parts that can run concurrently. Each part of such
a program is called a thread, and each thread defines a separate path of
execution.
 Thus, multithreading is a specialized form of multitasking.

 There are two distinct types of multitasking: process-based and thread-based.


 In a thread-based multitasking environment, the thread is the smallest unit of
dispatchable code. This means that a single program can perform two or more
tasks simultaneously. For instance, a text editor can format text at the same time
that it is printing, as long as these two actions are being performed by two
separate threads.

 Advantages of multithreading over multi-tasking:

 Processes are heavyweight tasks that require their own separate


address spaces. Inter-process communication is expensive and
limited. Context switching from one process to another is also
costly.
Threads, on the other hand, are lightweight. They share the same
address space and cooperatively share the same heavyweight
process. Interthread communication is inexpensive, and context
switching from one thread to the next is low cost.

 Reduces the computation time.

 Improves performance of an application.


 Thread:
 A thread is a sequential path of code execution within a program. And each
thread has its own local variables, program counter and lifetime.

 In Java, an object of the Thread class can represent a thread.

 THREAD LIFE CYCLE:

 When you are programming with threads, understanding the


life cycle of thread is very valuable. While a thread is alive, it is in one of
several states. By invoking start () method, it doesn’t mean that the thread
has access to CPU and start executing straight away. Several factors
determine how it will proceed.

 Thread States or Thread Life Cycle

1. New state – After the construction of Thread instance the thread is in


this state but before the start() method invocation. At this point, the thread
is considered not alive.

2. Runnable (Ready-to-run) state – A thread start its life from Runnable


state. A thread first enters runnable state after the invoking of start()
method but a thread can come again to this state after either running,
waiting, sleeping or coming back from blocked state also. On this state a
thread is waiting for a turn on the processor.

3. Running state – A thread is in running state that means the thread is


presently executing. There are numerous ways to enter in Runnable state
but there is only one way to enter in Running state: the scheduler select a
thread from runnable pool.

4. Dead state – A thread can be considered dead when its run() method
completes. If any thread comes on this state that means it cannot ever run
again.

5. Blocked - A thread can enter in this state because of waiting the


resources that are hold by another thread.

 The Thread Class and the Runnable Interface


 Java’s multithreading system is built upon the Thread class, its methods,
and its companion interface, Runnable. Thread encapsulates a thread of
execution.
 Since you can’t directly refer to the ethereal state of a running thread, you
will deal with it through its proxy, the Thread instance that spawned it.
 To create a new thread, your program will either extend Thread or
implement the Runnable interface.
 The Thread class defines several methods that help manage threads. The
ones that will be used in this chapter are shown here:
S.N Method & Description
1 static int activeCount()
This method returns the number of active threads in the current thread's
thread group.
2 void checkAccess()
This method determines if the currently running thread has permission to
modify this thread.
3 protected Object clone()
This method returns a clone if the class of this object is Cloneable.
4 static Thread currentThread()
This method returns a reference to the currently executing thread object.
5 static void dumpStack()
This method prints a stack trace of the current thread to the standard error
stream.
6 static int enumerate(Thread[] tarray)
This method copies into the specified array every active thread in the current
thread's thread group and its subgroups.
7 static Map<Thread,StackTraceElement[]> getAllStackTraces()
This method returns a map of stack traces for all live threads.
8 ClassLoader getContextClassLoader()
This method returns the context ClassLoader for this Thread.
9 static Thread.UncaughtExceptionHandler
getDefaultUncaughtExceptionHandler()
This method returns the default handler invoked when a thread abruptly
terminates due to an uncaught exception.
10 long getId()
This method returns the identifier of this Thread.
11 String getName()
This method returns this thread's name.
12 int getPriority()
This method Returns this thread's priority.
13 StackTraceElement[] getStackTrace()
This method returns an array of stack trace elements representing the stack
dump of this thread.
14 Thread.State getState()
This method returns the state of this thread.
15 ThreadGroup getThreadGroup()
This method returns the thread group to which this thread belongs.
16 Thread.UncaughtExceptionHandler getUncaughtExceptionHandler()
This method returns the handler invoked when this thread abruptly
terminates due to an uncaught exception.
17 static boolean holdsLock(Object obj)
This method returns true if and only if the current thread holds the monitor
lock on the specified object.
18 void interrupt()
This method interrupts this thread.
19 static boolean interrupted()
This method tests whether the current thread has been interrupted.
20 boolean isAlive()
This method tests if this thread is alive.
21 boolean isDaemon()
This method tests if this thread is a daemon thread.
22 boolean isInterrupted()
This method tests whether this thread has been interrupted.
23 void join()
Waits for this thread to die.
24 void join(long millis)
Waits at most millis milliseconds for this thread to die.
25 void join(long millis, int nanos)
Waits at most millis milliseconds plus nanos nanoseconds for this thread to
die.
26 void run()
If this thread was constructed using a separate Runnable run object, then that
Runnable object's run method is called; otherwise, this method does nothing
and returns
27 void setContextClassLoader(ClassLoader cl)
This method sets the context ClassLoader for this Thread.
28 void setDaemon(boolean on)
This method marks this thread as either a daemon thread or a user thread.
29 static void
setDefaultUncaughtExceptionHandler(Thread.UncaughtExceptionHandler eh)
This method set the default handler invoked when a thread abruptly
terminates due to an uncaught exception, and no other handler has been
defined for that thread.
30 void setName(String name)
This method changes the name of this thread to be equal to the argument
name.
31 void setPriority(int newPriority)
This method changes the priority of this thread.
32 void setUncaughtExceptionHandler(Thread.UncaughtExceptionHandler eh)
This method set the handler invoked when this thread abruptly terminates due
to an uncaught exception.
33 static void sleep(long millis)
This method causes the currently executing thread to sleep (temporarily cease
execution) for the specified number of milliseconds, subject to the precision
and accuracy of system timers and schedulers.
34 static void sleep(long millis, int nanos)
This method causes the currently executing thread to sleep (cease execution)
for the specified number of milliseconds plus the specified number of
nanoseconds, subject to the precision and accuracy of system timers and
schedulers.
35 void start()
This method causes this thread to begin execution; the Java Virtual Machine
calls the run method of this thread.
36 String toString()
This method Returns a string representation of this thread, including the
thread's name, priority, and thread group.
37 static void yield()
This method causes the currently executing thread object to temporarily pause
and allow other threads to execute.

 The Main Thread


 When a Java program starts up, one thread begins running immediately.
This is usually called the main thread of your program, because it is the
one that is executed when your program begins. The main thread is
important for two reasons:
1. It is the thread from which other “child” threads will be
spawned.
2. Often it must be the last thread to finish execution because
it performs various shutdown actions.
 Although the main thread is created automatically when your program is started,
it can be controlled through a Thread object. To do so, you must obtain a
reference to it by calling the method currentThread( ), which is a public static
member of Thread.

 Its general form is shown here:


static Thread currentThread( )

 Let’s begin by reviewing the following example:


// Controlling the main Thread.
class CurrentThreadDemo {
public static void main(String args[]) {
Thread t = Thread.currentThread();
System.out.println("Current thread: " + t);
// change the name of the thread
t.setName("My Thread");
System.out.println("After name change: " + t);
try {
for(int n = 5; n > 0; n--) {
System.out.println(n);
Thread.sleep(1000);
}
} catch (InterruptedException e) {
System.out.println("Main thread interrupted");
}
}
}
 This example just prints a message if it gets interrupted. In a real program,
you would need to handle this differently.
 Here is the output generated by this program:
Current thread: Thread[main,5,main]
After name change: Thread[My Thread,5,main]
5
4
3
2
1

 Creating a Thread
 In the most general sense, you create a thread by instantiating an object
of type Thread.
 Java defines two ways in which this can be accomplished:
1. You can implement the Runnable interface.
2. You can extend the Thread class, itself.

1. Implementing Runnable:
 The easiest way to create a thread is to create a class that implements the
Runnable interface.
 Runnable abstracts a unit of executable code. You can construct a thread
on any object that implements Runnable.
 To implement Runnable, a class need only implement a single method
called run( ), which is declared like this:
public void run( )
 Inside run( ), you will define the code that constitutes the new thread.
 It is important to understand that run( ) can call other methods, use other
classes, and declare variables, just like the main thread can.
 The only difference is that run( ) establishes the entry point for another,
concurrent thread of execution within your program. This thread will end
when run( ) returns.

 After you create a class that implements Runnable, you will instantiate an
object of type Thread from within that class. Thread defines several
constructors.
 The one that we will use is shown here:
Thread(Runnable threadOb, String threadName)
In this constructor, threadOb is an instance of a class that implements the
Runnable interface. The name of the new
thread is specified by threadName.

 After the new thread is created, it will not start running until you call its
start( ) method, which is declared within Thread. In essence, start( )
executes a call to run( ).

 Here is an example that creates a new thread and starts it running:


// Create a second thread.
class NewThread implements Runnable {
Thread t;
NewThread() {
// Create a new, second thread
t = new Thread(this, "Demo Thread");
System.out.println("Child thread: " + t);
t.start(); // Start the thread
}
// This is the entry point for the second thread.
public void run() {
try {
for(int i = 5; i > 0; i--) {
System.out.println("Child Thread: " + i);
Thread.sleep(500);
}
} catch (InterruptedException e) {
System.out.println("Child interrupted.");
}
System.out.println("Exiting child thread.");
}
}
class ThreadDemo {
public static void main(String args[]) {
new NewThread(); // create a new thread
try {
for(int i = 5; i > 0; i--) {
System.out.println("Main Thread: " + i);
Thread.sleep(1000);
}
} catch (InterruptedException e) {
System.out.println("Main thread interrupted.");
}
System.out.println("Main thread exiting.");
}
}
 The output produced by this program is as follows:
Child thread: Thread[Demo Thread,5,main]
Main Thread: 5
Child Thread: 5
Child Thread: 4
Main Thread: 4
Child Thread: 3
Child Thread: 2
Main Thread: 3
Child Thread: 1
Exiting child thread.
Main Thread: 2
Main Thread: 1
Main thread exiting.

2. Extending Thread
 The second way to create a thread is to create a new class that extends
Thread, and then to create an instance of that class.
// Create a second thread by extending Thread
class NewThread extends Thread {
NewThread() {
// Create a new, second thread
super("Demo Thread");
System.out.println("Child thread: " + this);
start(); // Start the thread
}
// This is the entry point for the second thread.
public void run() {
try {
for(int i = 5; i > 0; i--) {
System.out.println("Child Thread: " + i);
Thread.sleep(500);
}
} catch (InterruptedException e) {
System.out.println("Child interrupted.");
}
System.out.println("Exiting child thread.");
}
}
class ExtendThread {
public static void main(String args[]) {
new NewThread(); // create a new thread
try {
for(int i = 5; i > 0; i--) {
System.out.println("Main Thread: " + i);
Thread.sleep(1000);
}
} catch (InterruptedException e) {
System.out.println("Main thread interrupted.");
}
System.out.println("Main thread exiting.");
}
}

 Notice the call to super( ) inside NewThread. This invokes the


following form of the Thread constructor:
public Thread(String threadName)
Here, threadName specifies the name of the thread.

 There are two reasons for implementing a Runnable interface


preferable to extending the Thread Class:
1. If you extend the Thread Class, that means that subclass
cannot extend any other Class, but if you implement Runnable interface
then you can do this.
2. The class implementing the Runnable interface can avoid
the full overhead of Thread class which can be excessive.

 Creating Multiple Threads


following program creates three child threads:
// Create multiple threads.
class NewThread implements Runnable {
String name; // name of thread
Thread t;
NewThread(String threadname) {
name = threadname;
t = new Thread(this, name);
System.out.println("New thread: " + t);
t.start(); // Start the thread
}
// This is the entry point for thread.
public void run() {
try {
for(int i = 5; i > 0; i--) {
System.out.println(name + ": " + i);
Thread.sleep(1000);
}
} catch (InterruptedException e) {
System.out.println(name + "Interrupted");
}
System.out.println(name + " exiting.");
}
}

class MultiThreadDemo {
public static void main(String args[]) {
new NewThread("One"); // start threads
new NewThread("Two");
new NewThread("Three");
try {
// wait for other threads to end
Thread.sleep(10000);
} catch (InterruptedException e) {
System.out.println("Main thread Interrupted");
}
System.out.println("Main thread exiting.");
}
}

The output from this program is shown here:


New thread: Thread[One,5,main]
New thread: Thread[Two,5,main]
New thread: Thread[Three,5,main]
One: 5
Two: 5
Three: 5
One: 4
Two: 4
Three: 4
One: 3
Three: 3
Two: 3
One: 2
Three: 2
Two: 2
One: 1
Three: 1
Two: 1
One exiting.
Two exiting.
Three exiting.
Main thread exiting.
As you can see, once started, all three child threads share the CPU. Notice the
call to sleep(10000) in main( ). This causes the main thread to sleep for ten
seconds and ensures that it will finish last.

 Thread Priorities
 Thread priorities are used by the thread scheduler to decide when each
thread should be allowed to run. In theory, higher-priority threads get
more CPU time than lower-priority
threads.
 To set a thread’s priority, use the setPriority( ) method, which is a member
of Thread. This is its general form:
final void setPriority(int level)
 Here, level specifies the new priority setting for the calling thread.
 The value of level must be within the range MIN_PRIORITY and
MAX_PRIORITY. Currently, these
values are 1 and 10, respectively. To return a thread to default
priority, specify
NORM_PRIORITY, which is currently 5. These priorities are defined
as final variables within Thread.

 You can obtain the current priority setting by calling the getPriority( )
method of Thread, shown here:
final int getPriority( )

 Example:
class clicker implements Runnable {
int click = 0;
Thread t;
private volatile boolean running = true;

public clicker(int p) {
t = new Thread(this);
t.setPriority(p);
}
public void run() {
while (running) {
click++;
}
}
public void stop() {
running = false;
}
public void start() {
t.start();
}
}
class HiLoPri {
public static void main(String args[]) {
Thread.currentThread().setPriority(Thread.MAX_PRIORITY);
clicker hi = new clicker(Thread.NORM_PRIORITY + 2);
clicker lo = new clicker(Thread.NORM_PRIORITY - 2);
lo.start();
hi.start();
try {
Thread.sleep(10000);
} catch (InterruptedException e) {
System.out.println("Main thread interrupted.");
}
lo.stop();
hi.stop();
// Wait for child threads to terminate.
try {
hi.t.join();
lo.t.join();
} catch (InterruptedException e) {
System.out.println("InterruptedException caught");
}
System.out.println("Low-priority thread: " + lo.click);
System.out.println("High-priority thread: " + hi.click);
}
}

 Synchronization
 “When two or more threads need access to a shared resource, they need
some way to ensure that the resource will be used by only one thread at a
time. The process by which this is achieved is called synchronization.”
 Key to synchronization is the concept of the monitor (also called a
semaphore).
 A monitor is an object that is used as a mutually exclusive lock, or mutex.
Only one thread can own a monitor at a given time.
 When a thread acquires a lock, it is said to have entered the monitor. 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.

 You can synchronize your code in either of two ways.


1. Using Synchronized Methods
2. Using Synchronized Statement

1. Using Synchronized Methods


 Synchronization is easy in Java, because all objects have their own implicit
monitor associated with them. To enter an object’s monitor, just call a
method that has been modified with the synchronized keyword.
// This program is not synchronized.
class Callme {
void call(String msg) {
System.out.print("[" + msg);
try {
Thread.sleep(1000);
} catch(InterruptedException e) {
System.out.println("Interrupted");
}
System.out.println("]");
}
}
class Caller implements Runnable {
String msg;
Callme target;
Thread t;
public Caller(Callme targ, String s) {
target = targ;
msg = s;
t = new Thread(this);
t.start();
}
public void run() {
target.call(msg);
}
}
class Synch {
public static void main(String args[]) {
Callme target = new Callme();
Caller ob1 = new Caller(target, "Hello");
Caller ob2 = new Caller(target, "Synchronized");
Caller ob3 = new Caller(target, "World");
// wait for threads to end
try {
ob1.t.join();
ob2.t.join();
ob3.t.join();
} catch(InterruptedException e) {
System.out.println("Interrupted");
}
}
}
Here is the output produced by this program:
Hello[Synchronized[World]
]
]

 As you can see, by calling sleep( ), the call( ) method allows execution to
switch to another thread. This results in the mixed-up output of the three
message strings.
 In this program, nothing exists to stop all three threads from calling the
same method, on the same object, at the same time. This is known as a
race condition, because the three threads are racing each other to
complete the method.
 To fix the preceding program, you simply need to precede
call( )’s definition with the keyword synchronized, as shown here:
class Callme {
synchronized void call(String msg) {
 This prevents other threads from entering call( ) while another thread is
using it.

 After synchronized has been added to call( ), the output of the program
is as follows:
[Hello]
[Synchronized]
[World]

2. Using synchronized Statement

 Creating synchronized methods will not work in all cases. To understand


why, consider the following.
 Imagine that you want to synchronize access to objects of a class
that was not designed for multithreaded access. That is, the class
does not use synchronized methods. Further, this class was not
created by you, but by a third party, and you do not have access to
the source code. Thus, you can’t add synchronized to the
appropriate methods within the class.
 How can access to an object of this class be synchronized?
Fortunately, the solution to this problem is quite easy:
 You simply put calls to the methods defined by this class inside a
synchronized block.
 This is the general form of the synchronized statement:
synchronized(object) {
// statements to be synchronized
}
 Here, object is a reference to the object being synchronized.
A synchronized block ensures that a call to a method that is
a member of object occurs only after the current thread has
successfully entered object’s monitor.

 Here is an alternative version of the preceding example, using a


synchronized blockwithin the run( ) method:
// This program uses a synchronized block.
class Callme {
void call(String msg) {
System.out.print("[" + msg);
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
System.out.println("Interrupted");
}
System.out.println("]");
}
}
class Caller implements Runnable {
String msg;
Callme target;
Thread t;
public Caller(Callme targ, String s) {
target = targ;
msg = s;
t = new Thread(this);
t.start();
}
// synchronize calls to call()
public void run() {
synchronized(target) { // synchronized block
target.call(msg);
}
}
}
class Synch1 {
public static void main(String args[]) {
Callme target = new Callme();
Caller ob1 = new Caller(target, "Hello");
Caller ob2 = new Caller(target, "Synchronized");
Caller ob3 = new Caller(target, "World");
// wait for threads to end
try {
ob1.t.join();
ob2.t.join();
ob3.t.join();
} catch(InterruptedException e) {
System.out.println("Interrupted");
}
}
}
 Here, the call( ) method is not modified by synchronized. Instead, the
synchronized statement is used inside Caller’s run( ) method. This
causes the same correct output as the preceding example, because each
thread waits for the prior one to finish before proceeding.

ThreadGroup

 ThreadGroup creates a group of threads. It defines these two constructors:


ThreadGroup(String groupName)
ThreadGroup(ThreadGroup parentOb, String groupName)

 For both forms, groupName specifies the name of the thread group. The first
version creates a new group that has the current thread as its parent. In the
second form, the parent is specified by parentOb.

The methods defined by ThreadGroup are shown in Table


 The following program, which creates two thread groups of two threads each,
illustrates this usage:
// Demonstrate thread groups.
class NewThread extends Thread {
boolean suspendFlag;
NewThread(String threadname, ThreadGroup tgOb) {
super(tgOb, threadname);
System.out.println("New thread: " + this);
suspendFlag = false;
start(); // Start the thread
}
// This is the entry point for thread.
public void run() {
try {
for(int i = 5; i > 0; i--) {
System.out.println(getName() + ": " + i);
Thread.sleep(1000);
synchronized(this) {
while(suspendFlag) {
wait();
}
}
}
} catch (Exception e) {
System.out.println("Exception in " + getName());
}
System.out.println(getName() + " exiting.");
}
void mysuspend() {
suspendFlag = true;
}
synchronized void myresume() {
suspendFlag = false;
notify();
}
}
class ThreadGroupDemo {
public static void main(String args[]) {
ThreadGroup groupA = new ThreadGroup("Group A");
ThreadGroup groupB = new ThreadGroup("Group B");
NewThread ob1 = new NewThread("One", groupA);
NewThread ob2 = new NewThread("Two", groupA);
NewThread ob3 = new NewThread("Three", groupB);
NewThread ob4 = new NewThread("Four", groupB);
System.out.println("\nHere is output from list():");
groupA.list();
groupB.list();
System.out.println();
System.out.println("Suspending Group A");
Thread tga[] = new Thread[groupA.activeCount()];
groupA.enumerate(tga); // get threads in group
for(int i = 0; i < tga.length; i++) {
((NewThread)tga[i]).mysuspend(); // suspend each thread
}
try {
Thread.sleep(4000);
} catch (InterruptedException e) {
System.out.println("Main thread interrupted.");
}
System.out.println("Resuming Group A");
for(int i = 0; i < tga.length; i++) {
((NewThread)tga[i]).myresume(); // resume threads in group
}
// wait for threads to finish
try {
System.out.println("Waiting for threads to finish.");
ob1.join();
ob2.join();
ob3.join();
ob4.join();
} catch (Exception e) {
System.out.println("Exception in Main thread");
}
System.out.println("Main thread exiting.");
}
}
Sample output from this program is shown here:
New thread: Thread[One,5,Group A]
New thread: Thread[Two,5,Group A]
New thread: Thread[Three,5,Group B]
New thread: Thread[Four,5,Group B]
Here is output from list():
java.lang.ThreadGroup[name=Group A,maxpri=10]
Thread[One,5,Group A]
Thread[Two,5,Group A]
java.lang.ThreadGroup[name=Group B,maxpri=10]
Thread[Three,5,Group B]
Thread[Four,5,Group B]
Suspending Group A
Three: 5
Four: 5
Three: 4
Four: 4
Three: 3
Four: 3
Three: 2
Four: 2
Resuming Group A
Waiting for threads to finish.
One: 5
Two: 5
Three: 1
Four: 1
One: 4
Two: 4
Three exiting.
Four exiting.
One: 3
Two: 3
One: 2
Two: 2
One: 1
Two: 1
One exiting.
Two exiting.
Main thread exiting.

Daemon Threads 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

No. Method Description


1) public void is used to mark the current thread as
setDaemon(boolean status) daemon thread or user thread.
2) public boolean isDaemon() is used to check that current is daemon.
Simple example of Daemon thread in java
public class TestDaemonThread1 extends Thread{
public void run(){
if(Thread.currentThread().isDaemon()){//checking for daemon thread
System.out.println("daemon thread work");
}
else{
System.out.println("user thread work");
}
}
public static void main(String[] args){
TestDaemonThread1 t1=new TestDaemonThread1();//creating thread
TestDaemonThread1 t2=new TestDaemonThread1();
TestDaemonThread1 t3=new TestDaemonThread1();

t1.setDaemon(true);//now t1 is daemon thread

t1.start();//starting threads
t2.start();
t3.start();
}
}

Output
daemon thread work
user thread work
user thread work

You might also like