1. OODP Module IV
VJCET 1
MODULE 4
SYLLABUS
ď‚— Input/Output:
ď‚— stream classes (byte stream and character stream classes)
ď‚— Reading console input.
ď‚— Files
ď‚— Threads:
ď‚— thread model
ď‚— use of Thread class and Runnable interface
ď‚— thread synchronization
ď‚— multithreading
I/O Basics
ď‚— Input refers to flow of data into a program and output means flow of data out of a
program.
ď‚— Input to a program may come from various sources like keyboard, mouse, memory, disk,
network.
ď‚— Output of a program may go to several destinations like screen, printer, memory, disk,
network.
ď‚— Data that is transferred is treated as a sequence of bytes or characters.
ď‚— Java uses concept of streams to represent ordered sequence of data.
Streams
ď‚· Java programs perform I/O through streams.
ď‚· A stream is an abstraction that either produces or consumes information.
ď‚· A stream is linked to a physical device by the JavaI/O system.
ď‚· All streams behave in the same manner, even if the actual physical devicesto which they
are linked differ. Thus, the same I/O classes and methods can be applied to any type of
device. This means that an input stream can abstract many different kinds of input: from a
disk file, a keyboard, or a network socket. Likewise, an outputstream may refer to the
console, a disk file, or a network connection.
2. OODP Module IV
VJCET 2
ď‚· Java implements streams within class hierarchies defined in the java.io package.
ď‚— Java streams are classified into two basic types:
ď‚— Input stream
ď‚— Output stream
ď‚— An input stream extracts(or reads) data from source(file) and sends it to the program.
Similarly an output stream takes data from the program and sends it to the
destination(file).
ď‚— Stream classes are categorized into two types based on the data on which they operate.
They are: Byte Stream and Character Stream.
Byte Streams and Character Streams
Java 2 defines two types of streams:
ď‚· Byte Stream
o It provides aconvenient means for handling input and output of bytes.
o Byte streams are used for reading or writing binary data.
ď‚· CharacterStream
o Itprovides a convenient means for handling input and output of characters.
o They use unicode.
o In some cases, character streams are more efficient than byte streams.
At the lowest level, all I/O is still byte-oriented. Thecharacter-based streams simply provide a
convenient and efficient means for handlingcharacters.
The Byte Stream Classes
ď‚· Byte streams are defined by using two class hierarchies. At the top are two abstract
classes: InputStream and OutputStream.
ď‚· These classes define several key methods that the other stream classes implement. Two of
the most important are read( ) and write( ), which, respectively, read and write bytes of
data. Both methods are declared as abstract inside InputStream and OutputStream.
They are overridden by derived stream classes.
ď‚· Each of these abstract classes has several concrete subclasses, that handle the differences
between various devices, such as diskfiles, network connections, and even memory
buffers.
ď‚· Must import java.io to use the stream classes.
3. OODP Module IV
VJCET 3
Byte Stream Classes
Stream Class Meaning
BufferedInputStream Buffered input stream
BufferedOutputStream Buffered output stream
ByteArrayInputStream Input stream that reads from a byte array
ByteArrayOutputStream Output stream that writes to a byte array
DataInputStream An input stream that contains methods forreading the Java standard
data types
DataOutputStream An output stream that contains methods forwriting the Java
standard data types
FileInputStream Input stream that reads from a file
FileOutputStream Output stream that writes to a file
FilterInputStream Implements InputStream
FilterOutputStream Implements OutputStream
InputStream Abstract class that describes stream input
OutputStream Abstract class that describes stream output
PipedInputStream Input pipe
PipedOutputStream Output pipe
PrintStream Output stream that contains print( ) andprintln( )
PushbackInputStream Input stream that supports one-byte “unget,”which returns a byte to
the input stream
RandomAccessFile Supports random access file I/O
SequenceInputStream Input stream that is a combination of two ormore input streams that
will be readsequentially, one after the other
//Example using DataInputStream class of Byte Stream Classes
import java.io.*;
class inout
{
public static void main(String args[])throws IOException
{ int roll;
String name;
DataInputStream d=new DataInputStream(System.in);
System.out.println("Enter Roll No");
roll=Integer.parseInt(d.readLine());
System.out.println("Enter name");
name=d.readLine();
System.out.println("ROLL : "+roll);
System.out.println("NAME : "+name);
} }
//output:
4. OODP Module IV
VJCET 4
Eg:
/* Java Byte Streams Example
This example demonstrates how to read one byte from the input stream at a time. */
import java.io.*;
public class ReadByteStreams
{
public static void main(String args[])throws IOException
{
String str = args[0];
byte b[] = str.getBytes();
ByteArrayInputStream bais = new ByteArrayInputStream(b);
int r;
while ((r = bais.read()) != -1)
{
System.out.print((char) r + " ");
}
}
}
//Output:
CharacterStreamClasses
ď‚· Character streams are defined by using two class hierarchies. At the top are twoabstract
classes, Reader and Writer.
ď‚· These abstract classes handle Unicode character streams.
ď‚· The abstract classes Reader and Writer define several key methods that the otherstream
classes implement. Two of the most important methods are read() and write(),which read
and write characters of data, respectively. These methods are overridden by derived
stream classes.
Character Stream Classes
Stream Class Meaning
BufferedReader Buffered input character stream
BufferedWriter Buffered output character stream
CharArrayReader Input stream that reads from a character array
CharArrayWriter Output stream that writes to a character array
FileReader Input stream that reads from a file
FileWriter Output stream that writes to a file
5. OODP Module IV
VJCET 5
FilterReader Filtered reader
FilterWriter Filtered writer
InputStreamReader Input stream that translates bytes to characters
LineNumberReader Input stream that counts lines
OutputStreamWriter Output stream that translates charactersto bytes
PipedReader Input pipe
PipedWriter Output pipe
PrintWriter Output stream that contains print( ) andprintln( )
PushbackReader Input stream that allows characters to bereturned to the input stream
Reader Abstract class that describes characterstream input
StringReader Input stream that reads from a string
StringWriter Output stream that writes to a string
Writer Abstract class that describes characterstream output
Predefined Streams
ď‚· Java programs automatically import the java.lang package. This package defines a class
called System.
ď‚· System contains three predefined stream variables, in, out, and err. These fields are
declared as public and static within System.
o System.out refers to the standard output stream. By default, this is the console.
o System.in refers to standard input, which is the keyboard by default.
o System.err refers to the standard error stream, which also is the console by
default.
ď‚· These streams may be redirected to any compatible I/O device.
ď‚· System.in is an object of type InputStream
ď‚· System.out and System.err are objects of type PrintStream
Reading Console Input
In Java, console input is accomplished by reading from System.in. To obtain a character-based
stream that is attached to the console, we wrap System.in in a BufferedReader object, to create
a character stream. BufferedReader supports a buffered input stream. Its most commonly used
constructor is shown here:
BufferedReader(Reader inputReader)
Here, inputReader is the stream that is linked to the instance of BufferedReader that is being
created. Reader is an abstract class.
One of its concrete subclasses is InputStreamReader, which converts bytes to characters.
To obtain an InputStreamReader object that is linked to System.in, use the following
constructor:
6. OODP Module IV
VJCET 6
InputStreamReader(InputStream inputStream)
The following line of code creates a BufferedReader that is connected to the keyboard:
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
After this statement executes, br is a character-based stream that is linked to the console through
System.in.
//Example using BufferedReader and InputStreamReader Character stream class
import java.io.*;
class differ
{
public static void main(String args[]) throws IOException
{
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
System.out.println("Enter an integer");
int a = Integer.parseInt(br.readLine());
System.out.println("Enter a String");
String b = br.readLine();
System.out.printf("You have entered:- " + a +" and name as " + b);
}
}
Output
Enter an integer
12
Enter a String
cini
You have entered:- 12 and name as cini
Reading Characters
To read a character from a BufferedReader, use read( ).
int read( ) throws IOException
It reads a character from the input stream and returns an integer value. It returns –1 when the end
of the stream is encountered.
7. OODP Module IV
VJCET 7
Example :Read characters from the console
import java.io.*;
class BRRead
{ public static void main(String args[]) throws IOException
{
char c;
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
System.out.println("Enter characters, 'q' to quit.");
do
{
c = (char) br.read();
System.out.println(c);
} while(c != 'q');
}
}
Output :
Enter characters, 'q' to quit.
123abcq
1
2
3
a
b
c
q
System.in is line buffered. This means that no input is actually passed to the program until we
press ENTER. So it is better to not use read( ) for interactive console input.
Reading Strings
To read a string from the keyboard, use readLine() that is a member of the BufferedReader
class.
Syntax :
String readLine( ) throws IOException
8. OODP Module IV
VJCET 8
Example : The program reads and displays lines of text until you enter the word “stop”:
import java.io.*;
class BRReadLines
{
public static void main(String args[]) throws IOException
{
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
String str;
System.out.println("Enter lines of text.");
System.out.println("Enter 'stop' to quit.");
do
{
str = br.readLine();
System.out.println(str);
} while(!str.equals("stop"));
}
}
Output:
Example : To create a tiny text editor [or to write a program to read 100 lines of text or until
stop is entered and store it in an array. Display the array.]
import java.io.*;
class TinyEdit
{
public static void main(String args[])throws IOException
{
BufferedReader br = new BufferedReader(newInputStreamReader(System.in));
String str[] = new String[100];
System.out.println("Enter lines of text.");
System.out.println("Enter stop to quit.");
for(inti=0; i<100; i++)
{
str[i] = br.readLine();
if(str[i].equals("stop")) break;
}
System.out.println("nHere is your file:");
9. OODP Module IV
VJCET 9
for(int i=0; i<100; i++)
{
if(str[i].equals("stop")) break;
System.out.println(str[i]);
}
}
}
Output :
Enter lines of text.
Enter stop to quit.
This is line one.
This is line two.
Java makes working with strings easy.
Just create String objects.
stop
Here is your file:
This is line one.
This is line two.
Java makes working with strings easy.
Just create String objects.
Writing Console Output
print() and println() methods are defined by the class PrintStream(which is the type of the
object referenced by System.out). Because PrintStream is an output stream derived from
OutputStream, it also implements the low-level method write(). Thus, write() can be used to
write to the console.
Syntax :
void write(int byteval)
This method writes to the stream the byte specified by byteval. Although byteval is declared as
an integer, only the low-order eight bits are written.
Example: Output character “A” followed by a newline to the screen by using write():
class WriteDemo
{
public static void main(String args[])
{
int b;
b = 'A';
System.out.write(b);
System.out.write('n');
}
}
10. OODP Module IV
VJCET 10
The PrintWriter Class
The recommended method ofwriting to the console when using Java is through a PrintWriter
stream. PrintWriter is one of the character-based classes. PrintWriter defines several
constructors. The one we will use is shown here:
PrintWriter(OutputStream outputStream, boolean flushOnNewline)
Here, outputStream is an object of type OutputStream, and flushOnNewline controls whether
Java flushes the output stream every time a println( ) method is called. IfflushOnNewlineis true,
flushing automatically takes place. If false, flushing is not automatic.
PrintWriter supports the print( ) and println( ) methods for all types including Object. Thus,
you can use these methods in the same way as they have been used with System.out. If an
argument is not a simple type, the PrintWriter methods call the object’s toString( ) method and
then print the result.
The following line of code creates a PrintWriter that is connected to console output
PrintWriter pw = new PrintWriter(System.out, true);
Example :
import java.io.*;
public class PrintWriterDemo
{
public static void main(String args[])
{
PrintWriter pw = new PrintWriter(System.out, true);
pw.println("This is a string");
int i = -7;
pw.println(i);
double d = 4.5e-7;
pw.println(d);
}
}
Output:
This is a string
-7
4.5E-7
Reading and Writing Files
In Java, all files are byte-oriented, and Java provides methods to read and write bytes from and to
a file. However, Java allows you to wrap a byte-oriented file stream within a character-based
11. OODP Module IV
VJCET 11
object. Two of the most often-used stream classes are FileInputStream and FileOutputStream,
which create byte streams linked to files.
To open a file, create an object of one of these classes, specifying the name of the file as an
argument to the constructor.
FileInputStream(String fileName) throws FileNotFoundException
FileOutputStream(String fileName) throws FileNotFoundException
Here, filename specifies the name of the file that we want to open. While creating an input
stream, if the file does not exist, then FileNotFoundException is thrown. For output streams, if
the file cannot be created, then FileNotFoundException is thrown.When an output file is
opened, any pre existing file by the same name is destroyed.
File Methods
ď‚— close() method is used to close a file. It is defined by both FileInputStream and
FileOutputStream
Syntax: void close( ) throws IOException
ď‚— read( ) : To read from a file, defined by FileInputStream
Syntax: int read( ) throws IOException
It reads a single byte from the file and returns the byte as an integer value. read( ) returns –1
when the end of the file is encountered.
ď‚— write( ) : To write to a file, defined by FileOutputStream.
Syntax: void write(int byteval) throws IOException
Writes the byte specified by byteval to the file. If an error occurs during writing, an
IOException is thrown.
Example : Write a program that uses read( ) to input and display the contents of a text file, the
name of which is specified as a command-line argument.
import java.io.*;
class ShowFile
{
public static void main(String args[]) throws IOException
{
int i;
FileInputStream fin;
try
{ fin = new FileInputStream(args[0]);
}
catch(FileNotFoundException e)
{ System.out.println("File Not Found"); return;
}
12. OODP Module IV
VJCET 12
catch(ArrayIndexOutOfBoundsException e)
{ System.out.println("Enter an argument"); return;
}
do
{
i = fin.read();
if(i != -1) System.out.print((char) i);
}while(i != -1);
fin.close();
}
}
Example : Write a program to copy a text file using write(). Input and output file names
are mentioned as command line arguments
import java.io.*;
class CopyFile
{
public static void main(String args[]) throws IOException
{ int i;
FileInputStream fin;
FileOutputStream fout;
try
{ fin = new FileInputStream(args[0]);
fout = new FileOutputStream(args[1]);
}
catch(FileNotFoundException e)
{ System.out.println("Input File Not Found"); return;
}
catch(ArrayIndexOutOfBoundsException e)
{ System.out.println("Usage: CopyFile From To"); return;
}
try
{ do
{
i = fin.read();
if(i != -1)
fout.write(i);
} while(i != -1);
}
catch(IOException e)
{ System.out.println("File Error"); }
fin.close(); fout.close();
} }
13. OODP Module IV
VJCET 13
Tutorial 7
Q1) Write a program to create a file that could store details of three students. Details include
rollno, name and address and are provided through keyboard.
Q2) Write a Java program that accepts N integers through console and sort them in ascending
order.
Q3) Write a java program that accepts integers from a file and display their sum.
14. OODP Module IV
VJCET 14
THREADS
Multithreading
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
o A process is a program that is executing.
o Process-based multitasking allows our computer to run two or more programs
concurrently
o Example: can use a Java compiler and a text editor simultaneously.
ď‚· Thread-based
o A single program can perform two or more tasks simultaneously
o Example : A text editor can format text at the same time that it is printing
Disadvantages of multitasking processes:
ď‚· Multitasking processes require more overhead than Multitasking threads.
ď‚· Processes are heavyweight tasks that require their own separate address spaces.
ď‚· Interprocess communication is expensive and limited.
ď‚· Context switching from one process to another is also costly.
Advantages of multithreaded programs:
ď‚· Threads are lightweight.
ď‚· They share the same address space.
ď‚· Interthread communication is inexpensive
ď‚· Context switching from one thread to the next is low cost.
Therefore, Java supports multithreaded multitasking.
Disadvantages of multithreaded programs :
ď‚· If we create too many threads, it will degrade the performance of our program because of
the overhead associated with context switching
Java supports multithreaded multitasking.
Every thread in Java is created and controlled by the java.lang.Thread class
15. OODP Module IV
VJCET 15
Thread Model(orThread Life Cycle)
ď‚· Newborn state :
o When we create a thread object, the thread is born and is said to be in newborn
state.
o This thread is not yet scheduled for running
o If we attempt to use any other method at this state, an exception will be thrown.
o The following things can be done at this state:
1. Schedule it for running using start() : it moves to the runnable state
2. Kill it using stop()
ď‚· Runnable State
o The thread is ready for execution and is waiting for the availability of the
processor
o The thread has joined the queue of threads that are waiting for execution.
o If all threads have equal priority, then they are given time slots for execution in
round robin fashion.
o The thread that relinquishes control joins the queue at the end and again waiting
for its turn.
ď‚· Running State
o The processor has given its time to the thread for its execution.
o The thread runs until it relinquishes control on its own or it is preempted by a
higher priority thread.
o A running thread relinquish its control in one of the following situations
1. It has been suspended using suspend(). A suspend thread can be revived
by using the resume().
16. OODP Module IV
VJCET 16
2. We can put a thread to sleep for a specified time period using the method
sleep(time) where time is in milliseconds. The thread re-enters the
runnable state as soon as this time period is elapsed.
3. It has been told to wait until some event occurs. This is done using the
wait(). The thread can be scheduled to run again using the notify().
ď‚· Blocked State
o A thread is said to be blocked when it is prevented from entering into the runnable
state and subsequently the running state
o This happens when the thread is suspended, sleeping, or waiting in order to satisfy
certain requirements
o A blocked thread is considered “not runnable: but not dead and therefore full
qualified to run again
ď‚· Dead State
o Natural death : A running thread ends its life when it has completed executing its
run().
o Premature death : We can kill a thread by sending the stop message to it at any
state
o A thread can be killed as soon as it is born, or while it is running, or even when it
is in blocked condition.
o At any time, a thread can be terminated, which halts its execution immediately.
Once terminated, a thread cannot be resumed.
The Thread Class and the Runnable Interface
Java’s multithreading system is built upon the Thread class and Runnable interface.
The Thread class defines several methods that help manage threads.
Method Meaning
getName Obtain a thread’s name
getPriority Obtain a thread’s priority
isAlive Determine if a thread is still running
join Wait for a thread to terminate
run Entry point for the thread
sleep Suspend a thread for a period of time
start Start a thread by calling its run method
The Main Thread
When a Java program starts up, one thread begins running immediately. This is called the main
thread of the program. It is the thread from which other “child” threads will be spawned. It must
be the last thread to finish execution because it performs various shutdown actions.
Current thread object is obtained by calling the method currentThread( ).
17. OODP Module IV
VJCET 17
General form:
static Thread currentThread( )
This method returns a reference to the thread in which it is called.
Example:
class CurrentThreadDemo
{
public static void main(String args[])
{
Thread t = Thread.currentThread();
System.out.println("Current thread: " + t);
t.setName("S4 CS");
System.out.println("After name change: " + t);
try
{ System.out.println("Im going to sleep like u");
for(int n = 5; n > 0; n--)
{ System.out.println(n);
Thread.sleep(1000);
}
}
catch (InterruptedException e)
{ System.out.println("Main thread interrupted");
}
}
}
Output :
Current thread: Thread[main,5,main]
After name change: Thread[S4 CS ,5,main]
I’m going to sleep like u
5
4
3
2
1
Here the reference to the current thread is stored in the local variable t.
t.setName( ) changes the internal name of the thread. The sleep() method in Thread might
throw an InterruptedException. This would happen if some other thread wanted to interrupt
this sleeping one.
[main,5,main] : the name of the main thread is main. Its priority is 5, which is the default value,
and main is also the name of the group of threads to which this thread belongs. A thread group
is a data structure that controls the state of a collection of threads as a whole.
18. OODP Module IV
VJCET 18
sleep( ) Syntax :
static void sleep(long milliseconds) throws InterruptedException
static void sleep(long milliseconds, int nanoseconds) throws InterruptedException
The number of milliseconds to suspend is specified in milliseconds and the number of
nanoseconds to suspend is specified in nanoseconds.
setName( ) and getName( ) Syntax:
final void setName(String threadName)
final String getName( )
Here, threadName specifies the name of the thread.
Creating a Thread
To create a Thread, Java adopts the following two ways :
ď‚· By implementing the Runnable interface
ď‚· By extending the Thread class
Implementing Runnable Interface
To implement Runnable interface, a class need only implement a single method called run().
Syntax :
public void run( )
Inside run( ), we can define the code that constitutes the new thread. run( ) can call other
methods, use other classes, and declare variables, just like the main thread can. This thread will
end when run( ) returns.
After creating a class that implements Runnable, we 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)
threadOb is an instance of a class that implements the Runnable interface. This defines where
execution of the thread will begin. The name of the new thread is specified by threadName.
After the new thread is created, call start( ) method to begin execution of the thread. start() is
declared within Thread.
Syntax of start( ): void start( )
Example:
import java.lang.*;
public class ThreadDemo1 implements Runnable {
Thread t;
19. OODP Module IV
VJCET 19
ThreadDemo1()
{ t = new Thread(this, "Admin Thread");// thread created
System.out.println("thread = " + t); // prints thread created
System.out.println("Calling run() function... ");
t.start();
}
public void run()
{ System.out.println("Inside run()function");
}
public static void main(String args[])
{
new ThreadDemo1();
}
}
Example2:
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)
20. OODP Module IV
VJCET 20
{
System.out.println("Child interrupted.");
}
System.out.println("Exiting child thread.");
}
}
class ThreadDemo
{
public static void main(String args[])
{
new NewThread(); // call constructor
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.");
}
}
Output :
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.
Inside NewThread’s constructor, a new Thread object is created by the following statement:
t = new Thread(this, "Demo Thread");
Demo Thread is the name of the child thread. start( ) starts the thread of execution by invoking
run( ). This causes the child thread’s for loop to begin. After calling start(), NewThread’s
21. OODP Module IV
VJCET 21
constructor returns to main( ). When the main thread resumes, it enters its for loop. Both threads
continue running, sharing the CPU, until their loops finish. In a multithreaded program, often the
main thread must be the last thread to finish running. Otherwise the Java run-time system may
hang.
Extending ThreadClass
Create a new class that extends Thread, and then to create an instance of that class. The
extending class must override the run( ) method, which is the entry point for the new thread. It
must also call start( ) to begin execution of the new thread.
Example:
class NewThread extends Thread
{
NewThread()
{
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--)
22. OODP Module IV
VJCET 22
{
System.out.println("Main Thread: " + i);
Thread.sleep(1000);
}
}
catch (InterruptedException e)
{
System.out.println("Main thread interrupted.");
}
System.out.println("Main thread exiting.");
}
}
This program generates the same output as the preceding version.
The child thread is created by instantiating an object of NewThread. super() inside invokes the
following form of the Thread constructor:
public Thread(String threadName)
Here, threadName specifies the name of the thread.
Creating Multiple Threads
Example : the following program creates three child 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)
23. OODP Module IV
VJCET 23
{
System.out.println(name + "Interrupted");
}
System.out.println(name + " exiting.");
}
}
class MultiThreadDemo
{
public static void main(String args[])
{
new NewThread("One");
new NewThread("Two");
new NewThread("Three");
try
{
Thread.sleep(10000);
}
catch (InterruptedException e)
{
System.out.println("Main thread Interrupted");
}
System.out.println("Main thread exiting.");
}
}
Output :
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.
24. OODP Module IV
VJCET 24
Main thread exiting.
Once started, all three child threads share the CPU.
We want the main thread to finish last. This is accomplished here by calling sleep( ) within
main( ). This is hardly a satisfactory solution.
Java provides two ways to determine whether a thread has finished.
ď‚· isAlive( )
o This method is defined by Thread
o Its general form is :
final boolean isAlive( )
This method returns true if the thread is still running. Otherwise it returns false.
ď‚· join( )
o Its general form is :
final void join( ) throws InterruptedException
o This method waits until the thread on which it is called terminates.
Example:
Output:
1 alive: true
2 alive: false
25. OODP Module IV
VJCET 25
3 alive: false
1 2 3 4 5
After thread t1
1 1 2 2 3 3 4 4 5 5
Thread Priorities
Java assigns to each thread a priority that determines how that thread should be treated with
respect to the others. Thread priorities are integer values. A thread’s priority is used for context
switch.
Rules for context switch :
ď‚· A thread can voluntarily relinquish control. In this scenario, all other threads are
examined, and the highest-priority thread that is ready to run is given the CPU.
ď‚· A thread can be preempted by a higher-priority thread. As soon as a higher-priority
thread wants to run, it does. This is called preemptive multitasking.
Higher-priority threads get more CPU time than lower priority threads. For instance, when a
lower-priority thread is running and a higher-priority thread resumes, it will preempt the lower-
priority thread. Threads of equal priority should get equal access to the CPU.
To set a thread’s priority, use the setPriority( ) method, which is a member of Thread.
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 (1) and MAX_PRIORITY (10). To return a thread to
default priority, specify NORM_PRIORITY (5). These priorities are defined as final variables
within Thread.
There are three constants defined in Thread class associated with priority.
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.
getPriority( ) is used to obtain the current priority of a Thread :
final int getPriority( )
26. OODP Module IV
VJCET 26
Example : two threads with different priorities
Output:
Thread Synchronization
When two or more threads need access to a shared resource(such as a linked list), they need
some way to ensure that the resource will be used by only one thread at a time. That is, we must
prevent one thread from writing data while another thread is in the middle of reading it. 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.
Synchronization can be achieved in two ways
ď‚· Using synchronized method
ď‚· Using synchronized statements
27. OODP Module IV
VJCET 27
Synchronized Methods
In Java 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. While a
thread is inside a synchronized method, all other threads that try to call it on the same instance
have to wait. To exit the monitor and relinquish control of the object to the next waiting thread,
the owner of the monitor simply returns from the synchronized method
Example : The following 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[])
{
28. OODP Module IV
VJCET 28
Callme target = new Callme();
Caller ob1 = new Caller(target, "Hello");
Caller ob2 = new Caller(target, "Synchronized");
Caller ob3 = new Caller(target, "World");
}
}
Output:
Hello[Synchronized[World]
]
]
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, we simply need to precede call( )’s definition with the keyword
synchronized
Synchronising above program:
class Callme
{
synchronized 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);
29. OODP Module IV
VJCET 29
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");
}
}
Output :
[Hello]
[Synchronized]
[World]
Once a thread enters any synchronized method on an instance, no other thread can enter any
other synchronized method on the same instance.
The synchronized Statement
Imagine that we want to synchronize access to objects of a class that was not designed for
multithreaded access. This class was not created by us, but by a third party, and we do not have
access to the source code. Thus, we can’t add synchronized to the appropriate methods within
the class. To access an object of this class in synchronized manner, simply put calls to the
methods defined by this class inside a synchronized block.
General form :
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.
Example :
class Callme
{
void call(String msg)
30. OODP Module IV
VJCET 30
{
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");
}
}
Output :
[Hello]
31. OODP Module IV
VJCET 31
[Synchronized]
[World]
Interthread Communication(or Thread managementFunctions)
ď‚— Java includes an interprocess communication mechanism via:
ď‚— wait( ) tells the calling thread to give up the monitor and go to sleep until some
other thread enters the same monitor and calls notify( ).
final void wait( ) throws InterruptedException
ď‚— notify( ) wakes up the first thread that called wait( ) on the same object.
final void notify( )
ď‚— notifyAll( ) wakes up all the threads that called wait( ) on the same object. The
highest priority thread will run first.
final void notifyAll( )
Example : correct implementation of a producer and consumer
// A correct implementation of a producer and consumer.
class Q
{
int n;
boolean valueSet = false;
synchronized int get()
{
if(!valueSet)
try
{
wait();
}
catch(InterruptedException e)
{
System.out.println("InterruptedException caught");
}
System.out.println("Got: " + n);
valueSet = false;
notify();
return n;
}
synchronized void put(int n)
{
if(valueSet)
try
{
wait();
}
32. OODP Module IV
VJCET 32
catch(InterruptedException e)
{
System.out.println("InterruptedException caught");
}
this.n = n;
valueSet = true;
System.out.println("Put: " + n);
notify();
}
}
class Producer implements Runnable
{
Q q;
Producer(Q q)
{
this.q = q;
new Thread(this, "Producer").start();
}
public void run()
{
int i = 0;
while(true)
{
q.put(i++);
}
}
}
class Consumer implements Runnable
{
Q q;
Consumer(Q q)
{
this.q = q;
new Thread(this, "Consumer").start();
}
public void run()
{
while(true)
{
q.get();
}
}
}
class PCFixed
{
public static void main(String args[])
33. OODP Module IV
VJCET 33
{
Q q = new Q();
new Producer(q);
new Consumer(q);
System.out.println("Press Control-C to stop.");
}
}
Output :
Put: 1
Got: 1
Put: 2
Got: 2
Put: 3
Got: 3
Put: 4
Got: 4
Put: 5
Got: 5
Inside get( ), wait( ) is called. This causes its execution to suspend until the Producer notifies
you that some data is ready. When this happens, execution inside get( ) resumes. After the data
has been obtained, get( ) calls notify( ). This tells Producer that it is okay to put more data in the
queue. Inside put( ), wait( ) suspends execution until the Consumer has removed the item from
the queue. When execution resumes, the next item of data is put in the queue, and notify( ) is
called. This tells the Consumer that it should now remove it.
Deadlock
Deadlock occurs when two threads have a circular dependency on a pair of synchronized objects.
Example : Suppose one thread enters the monitor on object X and another thread enters the
monitor on object Y. If the thread in X tries to call any synchronized method on Y, it will block.
However, if the thread in Y, in turn, tries to call any synchronized method on X, the thread waits
forever.
Example: create two classes, A and B, with methods foo( ) and bar( ), respectively, which pause
briefly before trying to call a method in the other class. The main class, named Deadlock, creates
an A and a B instance, and then starts a second thread to set up the deadlock condition. The foo(
) and bar( ) methods use sleep( ) as a way to force the deadlock condition to occur.
class A
{
synchronized void foo(B b)
{
String name = Thread.currentThread().getName();
System.out.println(name + " entered A.foo");
try
34. OODP Module IV
VJCET 34
{
Thread.sleep(1000);
}
catch(Exception e)
{
System.out.println("A Interrupted");
}
System.out.println(name + " trying to call B.last()");
b.last();
}
synchronized void last()
{
System.out.println("Inside A.last");
}
}
class B
{
synchronized void bar(A a)
{
String name = Thread.currentThread().getName();
System.out.println(name + " entered B.bar");
try
{
Thread.sleep(1000);
}
catch(Exception e)
{
System.out.println("B Interrupted");
}
System.out.println(name + " trying to call A.last()");
a.last();
}
synchronized void last()
{
System.out.println("Inside A.last");
}
}
class Deadlock implements Runnable
{
A a = new A();
B b = new B();
Deadlock()
{
Thread.currentThread().setName("MainThread");
Thread t = new Thread(this, "RacingThread");
t.start();
35. OODP Module IV
VJCET 35
a.foo(b); // get lock on a in this thread.
System.out.println("Back in main thread");
}
public void run()
{
b.bar(a); // get lock on b in other thread.
System.out.println("Back in other thread");
}
public static void main(String args[])
{
new Deadlock();
}
}
Output :
MainThread entered A.foo
RacingThread entered B.bar
MainThread trying to call B.last()
RacingThread trying to call A.last()
The program has deadlocked. The RacingThread owns the monitor on b, while it is waiting for
the monitor on a. At the same time, MainThread owns a and is waiting to get b. This program
will never complete.
Suspending, Resuming, and Stopping Threads in Java1.1 and Earlier
final void suspend( )
final void resume( )
Example:
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
}
public void run()
{
try
{
for(int i = 15; i > 0; i--)
{
System.out.println(name + ": " + i);
37. OODP Module IV
VJCET 37
}
Output :
New thread: Thread[One,5,main]
One: 15
New thread: Thread[Two,5,main]
Two: 15
One: 14
Two: 14
One: 13
Two: 13
One: 12
Two: 12
One: 11
Two: 11
Suspending thread One
Two: 10
Two: 9
Two: 8
Two: 7
Two: 6
Resuming thread One
Suspending thread Two
One: 10
One: 9
One: 8
One: 7
One: 6
Resuming thread Two
Waiting for threads to finish.
Two: 5
One: 5
Two: 4
One: 4
Two: 3
One: 3
Two: 2
One: 2
Two: 1
One: 1
Two exiting.
One exiting.
Main thread exiting.
The Thread class also defines a method called stop( ) that stops a thread. Once a thread has been
stopped, it cannot be restarted using resume( ).
38. OODP Module IV
VJCET 38
Syntax :
final void stop( )
Tutorial 8
Q1. Debug the following code:
class A extends Thread
{ public void run()
{ for(int i=1;i<=5;i++)
{ Thread.sleep(100);
}
}
}
Q2. Identify and correct error: