Professional Documents
Culture Documents
UNIT-4
Multi Threading, I/O Streams
Types of Multi-tasking:
• You expect programs to do many things at once, known as multi-tasking.
– Respond to a Mouse Click
– Spell Check Spelling
– Print
– Do Network Communications
– Do I/O
• Multi-tasking programs should have high performance, may utilize multiprocessors.
– There are two distinct types of multitasking: Process-based and Thread-based.
• The Program in execution is defined as Process. Thus, the process based multi tasking is the
feature that allows your computer to run two or more programs concurrently.
• In the thread-based multitasking environment, the thread is the smallest unit of dispatchable
code.
• This means that the single program can contain two or more parts, each part of the program is
executed in a separate path, called Thread.
• Ex: the text editor can be formatting the text and also printing the text in two different threads.
• Although the Java programs make use of the process-based multi tasking environments, but the
process-based multi tasking is not under the control of java, Where as the thread-based
multitasking is under the control of Java.
What is a Thread?
SingleThreadModel.java
class MyProgram
{
public void run()
{
for(int i=5; i>0;i--)
{
System.out.println("from child thread : " + i);
try {
Thread.sleep(1000);
}catch(InterruptedException ie) {}
}
}
}
class SingleThreadModel
{
public static void main(String args[] )
{
MyProgram mp1 = new MyProgram();
mp1.run();
for(int j=5; j>0;j--)
{
System.out.println("from main thread : " + j);
try {
Thread.sleep(1000);
}catch(InterruptedException ie) {}
}
}
}
Output:
MultiThreadModel.java
Output:
Creation of Thread
Creating the threads in the Java is simple. The threads can be implemented in the form of object
that contains a method "run()". The "run()" method is the heart and soul of any thread. It makes up the
entire body of the thread and is the only method in which the thread behavior can be implemented.
There are two ways to create thread.
1. Declare a class that extends the Thread class and override the run() method.
2. Declare a class that implements the Runnable interface which contains the run() method .
Example program:
class NewThread extends Thread {
NewThread() {
super("Demo Thread");
System.out.println("child thread: " + this);
start();
}
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 ExtendThreadDemo
{
public static void main(String[] args)
{
NewThread t1 = new NewThread();
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 interupted");
}
System.out.println("Main thread exiting.");
}
}
Output:
2. Implementing the Runnable Interface
The Runnable interface contains the run() method that is required for implementing the threads
in our program. To do this we must perform the following steps:
I. Declare a class as implementing the Runnable interface
II. Implement the run() method
III. Create a Thread by defining an object that is instantiated from this "runnable" class as the target
of the thread
IV. Call the thread's start() method to run the thread.
Example program:
class NewThread implements Runnable
{
Thread t;
NewThread() {
t = new Thread(this,"Demo Thread");
System.out.println("child thread: " + t);
t.start();
}
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 RunnableDemo
{
public static void main(String[] args)
{
NewThread t1 = new NewThread();
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 interupted");
}
System.out.println("Main thread exiting.");
}
}
Output:
For example, when a thread is waiting for I/O to complete, it lies in the blocked state. It’s the
responsibility of the thread scheduler to reactivate and schedule a blocked/waiting thread. A thread in
this state cannot continue its execution any further until it is moved to runnable state. Any thread in
these states do not consume any CPU cycle.
If a currently running thread is moved to blocked/waiting state, another thread in the runnable
state is scheduled by the thread scheduler to run. It is the responsibility of thread scheduler to
determine which thread to run.
When the sleep time is over, or any other thread called notify() method, or resume() method
and if I/O operation is completed the thread in Not-Runnable state is transitioned to Runnable state.
It is often very important to know which thread is ended. This helps to prevent the main from
terminating before the child Thread is terminating. To address this problem "Thread" class provides two
methods: 1) Thread.isAlive() 2) Thread.join().
The "isAlive()" method returns the either "TRUE" or "FALSE" . It returns "TRUE" if the thread is
alive, returns "FALSE" otherwise.
While isAlive( ) is occasionally useful, the method that you will more commonly use to wait for a
thread to finish is called join( ), shown here:
final void join( ) throws InterruptedException
This method waits until the thread on which it is called terminates. Its name comes from the
concept of the calling thread waiting until the specified thread joins it. Additional forms of join( ) allow
you to specify a maximum amount of time that you want to wait for the specified thread to terminate.
Program:
class NewThread extends Thread {
NewThread(String threadname) {
super(threadname);
System.out.println("New thread : " + this);
start();
}
public void run(){
try
{
for(int i=5; i>0;i--) {
System.out.println(getName() + " : " + i);
Thread.sleep(500);
}
}
catch (InterruptedException e){
System.out.println(getName() + " interrupted.");
}
System.out.println(getName() + " exiting...");
}
}
class JoinDemo
{
public static void main(String[] args) {
NewThread ob1 = new NewThread("One");
System.out.println("Thread One is alive : " + ob1.isAlive());
try
{
System.out.println("Waiting for child thread to finish....");
ob1.join();
}
catch (InterruptedException e) {
System.out.println("main thread Interrupted");
}
System.out.println("Thread One is alive : " + ob1.isAlive());
System.out.println("Main Thread exiting....");
}
}
Output:
Thread priorities :
Output:
running thread name is: Thread-0
running thread priority is: 10
running thread name is: Thread-1
running thread priority is: 1
Daemon thread:
A daemon thread is a thread that does not prevent the JVM from exiting when the program finishes but
the thread is still running.
An example for a daemon thread is the garbage collection.
You can use the setDaemon(boolean) method to change the Thread daemon properties before the
thread starts.
Daemon threads acts like service providers for other threads running in the same process.
Daemon threads will be terminated by the JVM when there are none of the other threads running, it
includes main thread of execution as well.
To determine if a thread is a daemon thread, use the accessor method isDaemon().
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. That particular code segment which contains
code to access or update the shared resource is known as critical section. Thread synchronization is
defined as a mechanism which ensures that two or more concurrent processes or threads do not
simultaneously execute the critical section.
Two or more threads executing simultaneously are called concurrent threads. Critical section is
part of the program, which contains code to access or modify the shared resource, and has to be
executed as an atomic action. Critical section is to be executed by only one thread at a time in
synchronization.
So synchronization mechanism takes care not to allow other threads to execute the critical
section.
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.
Example for Shared resource and critical section:
An Account is operating by two operations by two threads.
a) Depositing 1000 rs. By thread-1
b) Withdrawing 500 rs. By thread-2
Initial balance is Rs. 700/- after completing two operations the final effected balance is rs. 1200/-
So rs. 1200/- is consistent value after two operations.
After final updating by thread-2, the value in balance variable is Rs. 200/- , which is inconstant.
There are two types of thread synchronization mutual exclusive and inter-thread communication.
1. Mutual Exclusive
a) Synchronized method.
b) Synchronized block.
2. Cooperation (Inter-thread communication in java)
a) synchronized method:
class A
{
………
……..
synchronized void method1() {
// critical section code
}
………
………
}
• If you declare any method as synchronized, it is known as synchronized method.
• Synchronized method is used to lock an object for any shared resource.
• When a thread invokes a synchronized method, it automatically acquires the lock for that object and
releases it when the thread completes its task.
b) synchronized block:
• You do not have to synchronize a whole method. Sometimes it is preferable to synchronize only part
of a method. Java synchronized blocks inside methods makes this possible.
• Here is a synchronized block of Java code inside an unsynchronized Java method:
Synchronization is built around an internal entity known as the lock or monitor. Every object has
an lock associated with it. By convention, a thread that needs consistent access to an object's fields has
to acquire the object's lock before accessing them, and then release the lock when it's done with them.
So Synchronization avoids inconsistent values in the shared resources in concurrency control.
Disadvantages of Synchronization:
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);
t.start();
}
public void run() {
target.call(msg);
}
}
class SyncDemo
{
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");
try {
ob1.t.join();
ob2.t.join();
ob3.t.join();
}catch(InterruptedException e) {
System.out.println("Interrupted");
}
}
}
Output:
Case 2 : method is synchronized: ( remove comment around the word "synchronized" in line no:2 of
program.)
Inter-Thread Communication:
• To control Multi thread execution, and avoid conflicts, java provided a mechanism called Inter
Thread Communication.
• When conflict is occurred, the current thread goes into wait state, using wait() method, and it
provide chance to execute other thread.
• After conflict is solved, the second thread informed with notify() method, now first thread
resumed into running state.
• This process is called Inter Thread Communication.
wait() sleep()
wait() method releases the lock sleep() method doesn't release the lock.
should be notified by notify() or notifyAll() after the specified amount of time, sleep is
methods completed.
class Account
{
int amount=10000;
synchronized void withdraw(int amt)
{
System.out.println("going to withdraw...");
if(amount<amt){
System.out.println("Less balance; waiting for deposit...");
try{
wait();
}catch(Exception e){}
}
amount -= amt;
System.out.println("withdraw completed...");
System.out.println("Fresh Amount : " + amount);
}
class ITCDemo
{
public static void main(String args[])
{
final Account c=new Account();
System.out.println("Initial Amount : " + c.amount);
new Thread(){
public void run(){c.withdraw(15000);}
}.start();
new Thread(){
public void run(){c.deposit(10000);}
}.start();
}
}
Output:
Files and IO Streams
I/O Streams:
• A Stream is linked to a physical layer by java I/O system to make input and output operation in
java.
• In general, a stream means continuous flow of data.
• Streams are clean way to deal with input/output without having every part of your code
understand the physical.
• An I/O Stream represents an input source or an output destination.
• A stream can represent many different kinds of sources and destinations, including disk files,
devices, other programs, and memory arrays.
• Streams support many different kinds of data, including simple bytes, primitive data types,
localized characters, and objects.
• Some streams simply pass on data; others manipulate and transform the data in useful ways.
No matter how they work internally, all streams present the same simple model to programs
that use them: A stream is a sequence of data. A program uses an input stream to read data from a
source, one item at a time:
A program uses an output stream to write data to a destination, one item at time:
Java encapsulates Stream under java.io package. Java defines two types of streams. They are,
1. Byte Stream : It provides a convenient means for handling input and output of byte.
2. Character Stream : It provides a convenient means for handling input and output of characters.
Character stream uses Unicode and therefore can be internationalized.
3. Byte stream is defined by using two abstract class at the top of hierarchy, they are InputStream and
OutputStream.
These two abstract classes have several concrete classes that handle various devices such as disk
files, network connection etc.
Some important Byte stream classes.
Stream class Description
BufferedInputStream Used for Buffered Input Stream.
BufferedOutputStream Used for Buffered Output Stream.
DataInputStream Contains method for reading java standard datatype
DataOutputStream An output stream that contain method for writing java standard data type
FileInputStream Input stream that reads from a file
FileOutputStream Output stream that write to a file.
InputStream Abstract class that describe stream input.
OutputStream Abstract class that describe stream output.
PrintStream Output Stream that contain print() and println() method
These classes define several key methods. Two most important are
1. read() : reads byte of data.
2. write() : Writes byte of data.
These two abstract classes have several concrete classes that handle unicode character.
Some important Charcter stream classes.
Stream class Description
BufferedReader Handles buffered input stream.
BufferedWriter Handles buffered output stream.
FileReader Input stream that reads from file.
FileWriter Output stream that writes to file.
InputStreamReader Input stream that translate byte to character
OutputStreamWrite
Output stream that translate character to byte.
r
PrintWriter Output Stream that contain print() and println() method.
Reader Abstract class that define character stream input
Writer Abstract class that define character stream output
Reading Console Input
We use the object of BufferedReader class to take inputs from the keyboard.
Output:
Explanation:
a) System.in object is predefined object of InputStream class, and it can read the keyboard input as
binary data.
b) InputStreamReader object converts the binary data into character data.
c) Buffered Reader object stores character data in a buffered memory, and converts into a string object.
d) Interger.parseInt() methods converts the string data into numerical data.
java.io.File class:
• The java.io.File class object refers to a reference object to an actual physical file in the memory.
( like a FILE pointer in C language)
• This class is used to know the properties of a file like
– path of the file,
– whether the file exists or not,
– whether the file is a file or a directory,
– length of the file, etc.
java.io.File class methods:
File Constructors
o public File(String path)
o public File(String path, String name)
o public File(File dir, String name)
File Methods
o public String getName()
o public String getPath()
o public String getAbsolutePath()
o public String getParent()
o public boolean exists() throws SecurityException
o public boolean canWrite() throws SecurityException
o public boolean canRead() throws SecurityException
o public boolean isFile() throws SecurityException
o public boolean isDirectory() throws SecurityException
o public boolean isAbsolute()
o public long lastModified() throws SecurityException
o public long length() throws SecurityException
o public boolean mkdir()
o public boolean mkdirs() throws SecurityException
o public boolean renameTo(File destination) throws SecurityException
o public boolean delete() throws SecurityException
Output:
Reading Content from the file:
import java.io.*;
class ReadFileDemo{
public static void main(String args[]) throws Exception
{
File f1=new File(args[0]);
byte[] b={};
if(f1.exists()){
FileInputStream fis=new FileInputStream(f1);
b=new byte[fis.available()];
fis.read(b);
String s=new String(b);
System.out.println("Contents of "+args[0]+ ": \n"+ s);
fis.close();
}else{
System.out.println("File does not exist");
}
}
}
Output:
import java.io.*;
class WriteFileDemo{
public static void main(String args[]) throws Exception
{
FileOutputStream fos=new FileOutputStream(args[0]);
System.out.println("File Opened, now writing contents");
String str = "Welcome to java programming." +
"\nThis is example for File operations.";
byte[] b = str.getBytes();
fos.write(b);
fos.flush();
System.out.println("contents written");
System.out.println("Closing File");
fos.close();
}
}
Output:
import java.io.*;
public class CopyFile{
public static void main(String[] args) throws Exception
{
int i;
FileInputStream fin = new FileInputStream(args[0]);
FileOutputStream fout = new FileOutputStream(args[1]);
do {
i = fin.read();
if(i != -1) fout.write(i);
}while (i != -1);
fin.close();
fout.close();
}
}
Output:
RandomAccessFile
• The RandomAccessFile class provides a way to read from and write to a file in a nonsequential
manner.
• The constructor of RandomAccessFile class has two arguments. The first argument specifies the
file to open, either as a String or a File object.
• The second argument is a String that must be either "r" or "rw". If the second argument is "r",
the file is opened for reading only. If the argument is "rw", however, the file is opened for both
reading and writing.
RandomAccessFileDemo.java
import java.io.*;
class RandomAccessFileDemo {
public static void main(String args[]) throws Exception
{
RandomAccessFile raf = new RandomAccessFile(args[0], "rw");
raf.seek(10);
byte b1[] = new byte[15];
raf.read(b1);
System.out.println("Read from file : " + new String(b1));
raf.seek(raf.length());
String s1 = "This is end of the file.";
byte[] b2 = s1.getBytes();
raf.write(b2);
raf.close();
}
}
Output:
PART-A
PART-B
1. a) Write a Java program that prints numbers from 1 to 10 line by line after every 5 seconds
b) What is thread synchronization? Discuss with an example.
2. a) Write a Java program for creating four threads to perform the following operations
i) Getting N numbers as input ii) Printing the even numbers
iii) Printing the odd numbers iv) Computing the average
b) Explain how communication between threads takes place with a programming example.
3. a) Explain the following with necessary code snippets
i) Creating thread ii) Stopping and Blocking a Thread
b) "Threads can be given priorities" - Support this statement with suitable example.
4. a) Write a Java program to demonstrate multithreading operation.
b) Explain various thread states and properties in detail.
6. a) Explain life cycle of a thread with neat diagram
b) Discuss about thread synchronization.
7. a) Describe Java’s thread model.
b) What is a stream? What is the difference between byte streams and character streams? How are
they used to capture input from the user?
8. a) Write a program to implement multi thread programming.
b) Explain thread synchronization
9. a) Describe the need of thread synchronization. How is it achieved in Java programming? Explain with
a suitable program.
b) Differentiate between FileReader and BufferReader.
10. a) Explain thread life cycle and thread creation in Java.
b) Write a program to read user name from console and display some message for that user using
streams.
11. a) Explain about java.lang.thread package.
b) How to set priorities for threads? Discuss with examples.
12. a) What happen when PrintWriter method receives a string type argument?
b) Write a java program to display all odd numbered lines of a text file.
13. a) Discuss about reading console input.
b) Write a java program to implement producer consumer problem.
14. a) Write example that uses join ( ) to ensure that the main thread is the last to stop. Use isAlive () in
the same program.
b) Explain with example; explain how we set priority to threads.
15. a) Discuss about writing console output.
b) Write a java program to display all odd numbered lines of a text file.
16. a) Explain the Java thread model and its related issues in detail.
b) What is the need to assign priorities to threads? Explain with an example.
Assignment:
PART-A
PART-B
PROGRAMS:
1. Write a Java program that prints numbers from 1 to 10 line by line after every 5 seconds
2. Write a Java program for creating four threads to perform the following operations
i) Getting N numbers as input ii) Printing the even numbers
iii) Printing the odd numbers iv) Computing the average
3. Write a Java program to demonstrate multithreading operation.
4. Write a java program to display all odd numbered lines of a text file.
5. Write a program to read user name from console and display some message for that user using
streams.
6. Write a java program to implement producer consumer problem.