0% found this document useful (0 votes)
115 views26 pages

Unit 3 - Java

This document covers the concepts of multithreading and synchronization in Java, detailing the thread lifecycle, methods for creating threads, and the differences between multitasking, multiprocessing, and multithreading. It explains the importance of synchronization to prevent data corruption in multithreaded environments and provides examples of synchronized methods and blocks. Additionally, it discusses the advantages of multithreading, such as improved performance and independent thread execution.

Uploaded by

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

Unit 3 - Java

This document covers the concepts of multithreading and synchronization in Java, detailing the thread lifecycle, methods for creating threads, and the differences between multitasking, multiprocessing, and multithreading. It explains the importance of synchronization to prevent data corruption in multithreaded environments and provides examples of synchronized methods and blocks. Additionally, it discusses the advantages of multithreading, such as improved performance and independent thread execution.

Uploaded by

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

23UBCAC43/23UCSCC43 – PROGRAMMING IN JAVA UNIT 3

UNIT III: Thread Class-Runnable interface–Synchronization–Using


synchronized methods– Using synchronized statement-Inter thread
Communication–Deadlock. I/O Streams: Concepts of streams-Stream classes-
Byte and Character stream-Reading console Input and Writing Console output-
File Handling

What are Multitasking and the Types of Multitasking?


Multitasking is an approach to minimize execution time and maximize CPU
utilization by executing multiple tasks simultaneously. You can achieve the
process of multitasking in Java using two methods, as described below.

Multiprocessing in Java
Multiprocessing in Java is purely based on the number of processors available on
the host computer. Every process initiated by the user is sent to the CPU
(processor). It loads the registers on the CPU with the data related to the assigned
process.
To perform multiprocessing in Java, the user needs one processor. Therefore, when
the user requests the simultaneous execution of the second process, the alternate
CPU core gets triggered and executes the process.
Multithreading in Java
Multithreading in Java is a similar approach to multiprocessing. However, there are
some fundamental differences between the two. Instead of a physical processor,
multithreading involves virtual and independent threads.
It assigns each process with one or more threads based on their complexity. Each
thread is virtual and independent of the other. This makes process execution much

DEPARTMENT OF COMPUTRE SCIENCE –RAAK-Mrs.R SUGANYA -AP Page 1


23UBCAC43/23UCSCC43 – PROGRAMMING IN JAVA UNIT 3

safer. If a thread or two are terminated during an unexpected situation, the process
execution will not halt.

What is a Thread in Java?


A thread is the smallest segment of an entire process. A thread is an independent,
virtual and sequential control flow within a process. In process execution, it
involves a collection of threads, and each thread shares the same memory. Each
thread performs the job independently of another thread.

Sometimes, the processes might be interdependent for an intermediate result to


finish the process.

Life cycle of a thread.

DEPARTMENT OF COMPUTRE SCIENCE –RAAK-Mrs.R SUGANYA -AP Page 2


23UBCAC43/23UCSCC43 – PROGRAMMING IN JAVA UNIT 3

Above-mentioned stages are explained here:


New: A new thread begins its life cycle in the new state. It remains
in this state until the program starts the thread. It is also referred to
as a born thread.
Runnable: After a newly born thread is started, the thread
becomes runnable. A thread in this state is considered to be
executing its task.
Waiting: Sometimes, a thread transitions to the waiting state while
the thread waits for another thread to perform a task.A thread
transitions back to the runnable state only when another thread
signals the waiting thread to continue executing.
Timed waiting: A runnable thread can enter the timed waiting
state for a specified interval of time. A thread in this state
transitions back to the runnable state when that time interval
expires or when the event it is waiting for occurs.
Terminated Dead: A runnable thread enters the terminated state
when it completes its task or otherwise terminates.
What is Multithreading in Java?

DEPARTMENT OF COMPUTRE SCIENCE –RAAK-Mrs.R SUGANYA -AP Page 3


23UBCAC43/23UCSCC43 – PROGRAMMING IN JAVA UNIT 3

So far, you have looked into the process, thread, and thread lifecycle. You
understood that a computer executes a task via a thread. Now, you will learn the
process of multithreading in Java.
As the name suggests, multithreading in Java executes a complex process by
running a collection of threads simultaneously. Each thread belongs to the
Java.lang.Thread class. The thread class overrides the run() method and executes
the process.
Methods of Multithreading in Java
Following are the methods for Multithreading in Java.

The start method initiates the


start()
execution of a thread

The currentThread method


returns the reference to the
currentThread()
currently executing thread
object.

The run method triggers an


run()
action for the thread

The isAlive method is invoked


isAlive() to verify if the thread is alive
or dead

The sleep method is used to


sleep()
suspend the thread temporarily

The yield method is used to


send the currently executing
yield()
threads to standby mode and
runs different sets of threads

DEPARTMENT OF COMPUTRE SCIENCE –RAAK-Mrs.R SUGANYA -AP Page 4


23UBCAC43/23UCSCC43 – PROGRAMMING IN JAVA UNIT 3

on higher priority

The suspend method is used to


suspend() instantly suspend the thread
execution

The resume method is used to


resume() resume the execution of a
suspended thread only

The interrupt method triggers


interrupt() an interruption to the currently
executing thread class

The destroy method is invoked


destroy() to destroy the execution of a
group of threads

The stop method is used to


stop()
stop the execution of a thread

After the methods of Multithreading in Java, you will go through an example based
on Multithreading in Java.

Multithreading
Multithreading in Java is a process of executing multiple threads simultaneously.
A thread is a lightweight sub-process, the smallest unit of processing.
Multiprocessing and multithreading, both are used to achieve multitasking.
However, we use multithreading than multiprocessing because threads use a
shared memory area. They don't allocate separate memory area so saves memory,
and context-switching between the threads takes less time than process.
Java Multithreading is mostly used in games, animation, etc.

DEPARTMENT OF COMPUTRE SCIENCE –RAAK-Mrs.R SUGANYA -AP Page 5


23UBCAC43/23UCSCC43 – PROGRAMMING IN JAVA UNIT 3

Advantages of Java Multithreading


1. It doesn't block the user because threads are independent and you can
perform multiple operations at the same time.
2. You can perform many operations together, so it saves time.
3. Threads are independent, so it doesn't affect other threads if an exception
occurs in a single thread.

Multitasking
Multitasking is a process of executing multiple tasks simultaneously. We use
multitasking to utilize the CPU. Multitasking can be achieved in two ways:
1. Process-based Multitasking (Multiprocessing)
2. Thread-based Multitasking (Multithreading)
1) Process-based Multitasking (Multiprocessing)
• Each process has an address in memory. In other words, each process
allocates a separate memory area.
• A process is heavyweight.
• Cost of communication between the process is high.
• Switching from one process to another requires some time for
saving and loading registers, memory maps, updating lists, etc.
2) Thread-based Multitasking (Multithreading)
• Threads share the same address space.
• A thread is lightweight.
• Cost of communication between the thread is low.
Thread
A thread is a lightweight subprocess, the smallest unit of processing. It is a
separate path of execution.

DEPARTMENT OF COMPUTRE SCIENCE –RAAK-Mrs.R SUGANYA -AP Page 6


23UBCAC43/23UCSCC43 – PROGRAMMING IN JAVA UNIT 3

Threads are independent. If there occurs exception in one thread, it doesn't affect
other threads. It uses a shared memory area.

As shown in the above figure, a thread is executed inside the process. There is
context- switching between the threads. There can be multiple processes inside
the OS, and one process can have multiple threads.
Note: At a time one thread is executed only.
Thread class
Java provides Thread class to achieve thread programming. Thread class
provides constructors and methods to create and perform operations on a thread.
Thread class extends Object class and implements Runnable interface
Life cycle of a Thread (Thread States)
A thread can be in one of the five states. According to sun, there is only 4
states in thread life cycle in java new, runnable, non-runnable and terminated.
There is no running state.
But for better understanding the threads, we are explaining it in the 5 states.
The life cycle of the thread in java is controlled by JVM. The java thread states
are as follows:
• New
• Runnable
• Running

DEPARTMENT OF COMPUTRE SCIENCE –RAAK-Mrs.R SUGANYA -AP Page 7


23UBCAC43/23UCSCC43 – PROGRAMMING IN JAVA UNIT 3

• Non-Runnable (Blocked)
• Terminated
There are two ways to create a thread:
• By extending Thread class
• By implementing Runnable interface.

Thread class:
Thread class provide constructors and methods to create and perform operations
on a thread.Thread class extends Object class and implements Runnable interface.
Commonly used Constructors of Thread class:
• Thread()
• Thread(String name)
• Thread(Runnable r)
• Thread(Runnable r,String name)
Commonly used methods of Thread class:
• public void run(): is used to perform action for a thread.
• public void start(): starts the execution of the thread.JVM calls the
run() method on the thread.
• public void sleep(long miliseconds): Causes the currently executing
thread to sleep (temporarily cease execution) for the specified number of
milliseconds.
• public Thread currentThread(): returns the reference of currently
executing thread.
• public void yield(): causes the currently executing thread object to
temporarily pause and allow other threads to execute.
• public void suspend(): is used to suspend the thread(depricated).
• public void resume(): is used to resume the suspended thread(depricated).
• public void stop(): is used to stop the thread(depricated).
• public boolean isDaemon(): tests if the thread is a daemon thread.
• public void interrupt(): interrupts the thread.
• public boolean isInterrupted(): tests if the thread has been interrupted.
• public static boolean interrupted(): tests if the current thread has
been interrupted.

DEPARTMENT OF COMPUTRE SCIENCE –RAAK-Mrs.R SUGANYA -AP Page 8


23UBCAC43/23UCSCC43 – PROGRAMMING IN JAVA UNIT 3

Runnable interface:
The Runnable interface should be implemented by any class whose instances are
intended to be executed by a thread. Runnable interface have only one method
named run().
void run(): is used to perform action for a thread.
Starting a thread:
start() method of Thread class is used to start a newly created thread. It
performs following tasks:
• A new thread starts(with new callstack).
• The thread moves from New state to the Runnable state.
• When the thread gets a chance to execute, its target run() method will run.

1) Java Thread Example by extending Thread class


class Multi extends Thread
{
public void run()
{
System.out.println("thread is running...");
}
public static void main(String args[])
{
Multi t1=new Multi();
t1.start();
}
}
Output:thread is running...

2) Java Thread Example by implementing Runnable interface


class Multi3 implements Runnable
{
public void run()
DEPARTMENT OF COMPUTRE SCIENCE –RAAK-Mrs.R SUGANYA -AP Page 9
23UBCAC43/23UCSCC43 – PROGRAMMING IN JAVA UNIT 3

{
System.out.println("thread is running...");
}
public static void main(String args[])
{
Multi3 m1=new Multi3();
Thread t1 =new
Thread(m1); t1.start();
}
}

Output:thread is running...

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

1) New
The thread is in new state if you create an instance of Thread class but before
the invocation of start() method.

DEPARTMENT OF COMPUTRE SCIENCE –RAAK-Mrs.R SUGANYA -AP Page 10


23UBCAC43/23UCSCC43 – PROGRAMMING IN JAVA UNIT 3

2) Runnable
The thread is in runnable state after invocation of start() method, but the
thread scheduler has not selected it to be the running thread.
3) Running
The thread is in running state if the thread scheduler has selected it.
4) Non-Runnable (Blocked)
This is the state when the thread is still alive, but is currently not eligible to run.
5) Terminated
A thread is in terminated or dead state when its run() method exits
SYNCHRONIZATION–USING SYNCHRONIZED METHODS– USING
SYNCHRONIZED STATEMENT
Java, synchronization is used to control access to a shared resource by multiple
threads, ensuring that only one thread can access the resource at a time. This is
especially important in multithreaded environments where threads may conflict
and cause data corruption or unexpected behavior if they access the same resource
simultaneously.
Java provides two ways to implement synchronization: using synchronized
methods and synchronized blocks (statements). Here’s an explanation of both:
1. Synchronized Methods
A synchronized method is a method that is declared with the synchronized
keyword. When a thread calls this method, it acquires a lock (or monitor) on the
object the method belongs to. This means that only one thread can execute this
method at a time for that particular object.
Example of Synchronized Method:
class Counter {
private int count = 0;

// Synchronized method to ensure thread-safety


public synchronized void increment() {
count++;
}

public synchronized int getCount() {


return count;
}
DEPARTMENT OF COMPUTRE SCIENCE –RAAK-Mrs.R SUGANYA -AP Page 11
23UBCAC43/23UCSCC43 – PROGRAMMING IN JAVA UNIT 3

public class Main {


public static void main(String[] args) {
Counter counter = new Counter();

// Create multiple threads to test synchronization


Thread t1 = new Thread(() -> {
for (int i = 0; i < 1000; i++) {
counter.increment();
}
});

Thread t2 = new Thread(() -> {


for (int i = 0; i < 1000; i++) {
counter.increment();
}
});

t1.start();
t2.start();

try {
t1.join();
t2.join();
} catch (InterruptedException e) {
e.printStackTrace();
}

// Output the final count


System.out.println("Final count: " + counter.getCount()); // Expected: 2000
}
}

DEPARTMENT OF COMPUTRE SCIENCE –RAAK-Mrs.R SUGANYA -AP Page 12


23UBCAC43/23UCSCC43 – PROGRAMMING IN JAVA UNIT 3

 In this example, increment() and getCount() are synchronized methods,


ensuring that no two threads can execute these methods simultaneously for
the same Counter object.
 The use of synchronized ensures that the count value is updated correctly,
without race conditions.
2. Synchronized Statements (Blocks)
Sometimes, you may not need to synchronize an entire method, but rather just a
specific block of code within a method. This can improve performance by reducing
the scope of synchronization. You can do this using a synchronized block, which
allows you to specify the object on which the lock will be acquired.
Example of Synchronized Block:
class Counter {
private int count = 0;

// Synchronized block to ensure thread-safety only for the increment section


public void increment() {
synchronized (this) { // Locking the current object (this)
count++;
}
}

public int getCount() {


return count;
}
}

public class Main {


public static void main(String[] args) {
Counter counter = new Counter();

// Create multiple threads to test synchronization


Thread t1 = new Thread(() -> {
for (int i = 0; i < 1000; i++) {
counter.increment();
}
DEPARTMENT OF COMPUTRE SCIENCE –RAAK-Mrs.R SUGANYA -AP Page 13
23UBCAC43/23UCSCC43 – PROGRAMMING IN JAVA UNIT 3

});

Thread t2 = new Thread(() -> {


for (int i = 0; i < 1000; i++) {
counter.increment();
}
});

t1.start();
t2.start();

try {
t1.join();
t2.join();
} catch (InterruptedException e) {
e.printStackTrace();
}

// Output the final count


System.out.println("Final count: " + counter.getCount()); // Expected: 2000
}
}
In this example, the increment() method contains a synchronized block,
locking only the section of code where the shared resource (count) is
updated.
 You can also synchronize on different objects (e.g., synchronized
(someObject)), allowing fine-grained control over the synchronization.
Key Differences:
 Synchronized Method:
o Locks the entire method.
o Simpler to use, but may be less efficient if only part of the method
needs synchronization.
 Synchronized Block:
o Allows locking only specific code sections.

DEPARTMENT OF COMPUTRE SCIENCE –RAAK-Mrs.R SUGANYA -AP Page 14


23UBCAC43/23UCSCC43 – PROGRAMMING IN JAVA UNIT 3

o More flexible and potentially more efficient if the entire method


doesn’t need to be synchronized.
o You can lock on specific objects for more control.

INTERTHREAD COMMUNICATION

class SharedResource {
private int data = 0;
private boolean available = false;

// Consumer waits if data is not available


public synchronized void consume() throws InterruptedException {
while (!available) {
wait(); // Wait until the producer produces something
}
System.out.println("Consumed: " + data);
available = false; // Reset availability after consuming
notify(); // Notify producer that consumer has consumed the data
}

// Producer produces data and notifies the consumer


public synchronized void produce(int data) throws InterruptedException {
while (available) {
wait(); // Wait until the consumer consumes the data
}
this.data = data;
System.out.println("Produced: " + data);
available = true; // Set availability to true for the consumer
notify(); // Notify consumer that data is available
}
}

public class ProducerConsumer {


public static void main(String[] args) {
SharedResource resource = new SharedResource();
DEPARTMENT OF COMPUTRE SCIENCE –RAAK-Mrs.R SUGANYA -AP Page 15
23UBCAC43/23UCSCC43 – PROGRAMMING IN JAVA UNIT 3

// Producer thread
Thread producer = new Thread(() -> {
try {
for (int i = 1; i <= 5; i++) {
resource.produce(i);
Thread.sleep(1000); // Simulate time taken to produce
}
} catch (InterruptedException e) {
e.printStackTrace();
}
});

// Consumer thread
Thread consumer = new Thread(() -> {
try {
for (int i = 1; i <= 5; i++) {
resource.consume();
Thread.sleep(2000); // Simulate time taken to consume
}
} catch (InterruptedException e) {
e.printStackTrace();
}
});

producer.start();
consumer.start();
}
}
Explanation:
 The SharedResource class has a shared resource (data) that the producer
and consumer access.
 The producer produces data, while the consumer consumes it.
 wait() is used in the consume() method, where the consumer waits until data
is available. It waits on the object (the shared resource) and releases the lock.
DEPARTMENT OF COMPUTRE SCIENCE –RAAK-Mrs.R SUGANYA -AP Page 16
23UBCAC43/23UCSCC43 – PROGRAMMING IN JAVA UNIT 3

 notify() is used in the produce() method to notify the consumer that data is
available for consumption.
 If the consumer tries to consume before the producer produces data, it will
wait until the producer notifies it.
Flow of Execution:
1. The producer thread produces data and sets the available flag to true, then
calls notify().
2. The consumer thread consumes the data, setting the available flag to false,
then calls notify().
3. If the producer has produced data, the consumer can consume it. If not, the
consumer will wait.
4. The producer waits if the consumer hasn't consumed the data.
Important Notes:
 Deadlock: It is important to carefully design the wait-notify interactions to
avoid deadlocks, where two threads are waiting indefinitely for each other to
release resources.
 wait() and notify() must be used inside synchronized blocks or methods
because they need to acquire the intrinsic lock of the object before they can
be called.
Key Takeaways:
 wait(): Puts the current thread into a waiting state until it's notified.
 notify(): Wakes up one thread waiting on the same object.
 notifyAll(): Wakes up all threads waiting on the same object.
Interthread communication using wait() and notify() is crucial in scenarios where
threads must cooperate or synchronize their actions.

Deadlock in a multithreaded environment refers to a situation where two or more


threads are blocked forever, waiting for each other to release resources. This can
occur when each thread holds a lock that the other thread is trying to acquire.
Deadlocks can cause your program to freeze or behave unpredictably.
Conditions for Deadlock:
Deadlock occurs if the following four conditions are met simultaneously:
1. Mutual Exclusion: At least one resource is held in a non-shareable mode.
Only one thread can access a resource at a time.
2. Hold and Wait: A thread holding a resource is waiting for additional
DEPARTMENT OF COMPUTRE SCIENCE –RAAK-Mrs.R SUGANYA -AP Page 17
23UBCAC43/23UCSCC43 – PROGRAMMING IN JAVA UNIT 3

resources that are currently being held by other threads.


3. No Preemption: Resources cannot be forcibly taken from a thread holding
them. The resources must be released voluntarily.
4. Circular Wait: A set of threads are each waiting for a resource that another
thread in the set holds, creating a circular dependency.
Example of Deadlock:
Let's look at a classic example of a deadlock situation involving two threads and
two resources.
Scenario:
 Thread 1 holds lock on Resource 1 and waits for Resource 2.
 Thread 2 holds lock on Resource 2 and waits for Resource 1.
This leads to a deadlock because neither thread can proceed until it gets the
resource held by the other thread.
Code Example of Deadlock:
class Resource1 {
synchronized void method1(Resource2 r2) {
System.out.println("Thread 1: Holding Resource 1...");
try { Thread.sleep(1000); } catch (InterruptedException e) {}
System.out.println("Thread 1: Waiting for Resource 2...");
r2.lastMethod(); // Calling method of Resource2
}

synchronized void lastMethod() {


System.out.println("Thread 1: In Resource 1 last method");
}
}

class Resource2 {
synchronized void method2(Resource1 r1) {
System.out.println("Thread 2: Holding Resource 2...");
try { Thread.sleep(1000); } catch (InterruptedException e) {}
System.out.println("Thread 2: Waiting for Resource 1...");
r1.lastMethod(); // Calling method of Resource1
}

DEPARTMENT OF COMPUTRE SCIENCE –RAAK-Mrs.R SUGANYA -AP Page 18


23UBCAC43/23UCSCC43 – PROGRAMMING IN JAVA UNIT 3

synchronized void lastMethod() {


System.out.println("Thread 2: In Resource 2 last method");
}
}

public class DeadlockExample {


public static void main(String[] args) {
Resource1 r1 = new Resource1();
Resource2 r2 = new Resource2();

// Thread 1 tries to access Resource1, then Resource2


Thread t1 = new Thread(() -> r1.method1(r2));

// Thread 2 tries to access Resource2, then Resource1


Thread t2 = new Thread(() -> r2.method2(r1));

t1.start();
t2.start();
}
}
How Deadlock Occurs in the Above Example:
1. Thread 1 acquires a lock on Resource1 and then tries to acquire a lock on
Resource2.
2. Thread 2 acquires a lock on Resource2 and tries to acquire a lock on
Resource1.
3. Now, Thread 1 is waiting for Thread 2 to release Resource2, and Thread 2
is waiting for Thread 1 to release Resource1.
4. Neither thread can proceed, resulting in a deadlock.
Ways to Avoid Deadlock:
1. Lock Ordering (Prevention):
o Establish a global order in which locks must be acquired by all
threads. If all threads acquire locks in the same order, circular waiting
is prevented.
synchronized (Resource1.class) {
synchronized (Resource2.class) {
DEPARTMENT OF COMPUTRE SCIENCE –RAAK-Mrs.R SUGANYA -AP Page 19
23UBCAC43/23UCSCC43 – PROGRAMMING IN JAVA UNIT 3

// Safe access to both resources


}
}
2. Timeouts:
o Allow threads to try to acquire locks for a certain amount of time, and
if they can’t get all required locks, they can release the ones they’ve
acquired and retry.
o This can be done using ReentrantLock with tryLock() method.
Lock lock1 = new ReentrantLock();
Lock lock2 = new ReentrantLock();

if (lock1.tryLock() && lock2.tryLock()) {


try {
// Critical section code
} finally {
lock1.unlock();
lock2.unlock();
}
} else {
// Retry or handle the failure
}
3. Deadlock Detection:
o Detecting deadlocks can be complex and may require analyzing the
system for circular dependencies between threads. This method is
typically used in database systems or other environments that need a
more systematic approach to detect and recover from deadlocks.
4. Using ReentrantLock:
o The ReentrantLock class in Java allows more control over locking.
For instance, you can use lockInterruptibly() to make the thread
interruptible and avoid getting stuck in a deadlock situation.
Key Takeaways:
 Deadlock is a situation where two or more threads are blocked forever,
waiting for each other to release resources.
 The four conditions for deadlock are: mutual exclusion, hold and wait, no
preemption, and circular wait.
DEPARTMENT OF COMPUTRE SCIENCE –RAAK-Mrs.R SUGANYA -AP Page 20
23UBCAC43/23UCSCC43 – PROGRAMMING IN JAVA UNIT 3

 Deadlock prevention techniques include lock ordering, timeouts, and


deadlock detection.
I/O Streams in Java
In Java, I/O (Input/Output) streams are used for reading and writing data. Java
provides a powerful set of classes and interfaces to handle I/O operations. Streams
represent input and output of data between your program and external sources like
files, networks, or console.
Key Concepts of I/O Streams:
 Stream: A stream represents a sequence of data. In Java, it is a flow of data
between the program and an I/O device (like a file, network, or console).
 Byte Streams: These handle I/O of raw binary data (bytes). They are used
for reading/writing all types of data (text, images, videos, etc.).
 Character Streams: These handle I/O of character data (text) and work
with Unicode characters. They are used for reading and writing text files.
 Input Stream: Used to read data.
 Output Stream: Used to write data.
1. Stream Classes
 Java provides many classes that implement the InputStream and
OutputStream interfaces (for byte data) and Reader and Writer classes (for
character data).
Byte Streams (For handling binary data)
Byte stream classes are used for reading and writing 8-bit binary data, like image
files, audio files, etc. These include:
 InputStream: The abstract class for all byte input streams.
 OutputStream: The abstract class for all byte output streams.
Examples of byte stream classes:
 FileInputStream: Reads byte data from a file.
 FileOutputStream: Writes byte data to a file.
 BufferedInputStream: Reads data in large chunks to improve performance.
 BufferedOutputStream: Writes data in large chunks.
Character Streams (For handling text data)
Character stream classes are used for reading and writing 16-bit Unicode
characters. These are used specifically for working with text files (e.g., .txt, .csv).
 Reader: The abstract class for all character input streams.
 Writer: The abstract class for all character output streams.

DEPARTMENT OF COMPUTRE SCIENCE –RAAK-Mrs.R SUGANYA -AP Page 21


23UBCAC43/23UCSCC43 – PROGRAMMING IN JAVA UNIT 3

Examples of character stream classes:


 FileReader: Reads character data from a file.
 FileWriter: Writes character data to a file.
 BufferedReader: Reads text from a file or stream efficiently (by buffering
characters).
 BufferedWriter: Writes text to a file or stream efficiently.

2. Reading Console Input and Writing Console Output


Reading from the Console (User Input)
To read input from the console, you can use:
1. Scanner (a higher-level class, most common)
2. BufferedReader (for reading lines of text)
Using Scanner for console input:
import java.util.Scanner;

public class ConsoleInputExample {


public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);

System.out.print("Enter your name: ");


String name = scanner.nextLine();

System.out.println("Hello, " + name + "!");

scanner.close();
}
}
Scanner is easy to use and provides methods like nextInt(), nextLine(), etc.,
for different types of input.
Using BufferedReader for console input:
import java.io.*;

public class ConsoleInputExample {


public static void main(String[] args) {
try {
DEPARTMENT OF COMPUTRE SCIENCE –RAAK-Mrs.R SUGANYA -AP Page 22
23UBCAC43/23UCSCC43 – PROGRAMMING IN JAVA UNIT 3

BufferedReader reader = new BufferedReader(new


InputStreamReader(System.in));
System.out.print("Enter your name: ");
String name = reader.readLine();
System.out.println("Hello, " + name + "!");
} catch (IOException e) {
e.printStackTrace();
}
}
}
 BufferedReader is used for more efficient reading of large chunks of text.
 readLine() reads an entire line of input.
Writing to the Console (User Output)
For writing to the console, we typically use:
1. System.out.print(): Prints text without a newline.
2. System.out.println(): Prints text with a newline.
Example:
public class ConsoleOutputExample {
public static void main(String[] args) {
System.out.println("Hello, World!");
System.out.print("This is a message without newline");
}
}
 System.out is an instance of PrintStream, which is a subclass of
OutputStream.

3. File Handling in Java


File handling is the process of reading from and writing to files. Java provides
various classes to perform file operations.
Writing Data to a File
Using FileWriter (character stream):
import java.io.*;

public class FileWriteExample {


public static void main(String[] args) {
DEPARTMENT OF COMPUTRE SCIENCE –RAAK-Mrs.R SUGANYA -AP Page 23
23UBCAC43/23UCSCC43 – PROGRAMMING IN JAVA UNIT 3

try {
FileWriter writer = new FileWriter("output.txt");
writer.write("Hello, this is a test file.");
writer.close();
System.out.println("Data written to file.");
} catch (IOException e) {
e.printStackTrace();
}
}
}
FileWriter writes characters to a file. It creates the file if it does not exist
and overwrites it if the file already exists.
Using BufferedWriter (more efficient):
import java.io.*;

public class BufferedFileWriteExample {


public static void main(String[] args) {
try {
BufferedWriter writer = new BufferedWriter(new FileWriter("output.txt"));
writer.write("Hello, this is a test file with BufferedWriter.");
writer.newLine(); // Writes a newline character
writer.close();
System.out.println("Data written to file.");
} catch (IOException e) {
e.printStackTrace();
}
}
}
 BufferedWriter is used to write data efficiently in chunks.
Reading Data from a File
Using FileReader (character stream):
import java.io.*;

public class FileReadExample {


public static void main(String[] args) {
DEPARTMENT OF COMPUTRE SCIENCE –RAAK-Mrs.R SUGANYA -AP Page 24
23UBCAC43/23UCSCC43 – PROGRAMMING IN JAVA UNIT 3

try {
FileReader reader = new FileReader("input.txt");
int character;
while ((character = reader.read()) != -1) {
System.out.print((char) character);
}
reader.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
FileReader reads characters from a file.
Using BufferedReader for efficient file reading:
import java.io.*;

public class BufferedFileReadExample {


public static void main(String[] args) {
try {
BufferedReader reader = new BufferedReader(new
FileReader("input.txt"));
String line;
while ((line = reader.readLine()) != null) {
System.out.println(line);
}
reader.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
 BufferedReader reads text from a file line by line.

4. Summary of Important I/O Classes


 Byte Stream Classes:

DEPARTMENT OF COMPUTRE SCIENCE –RAAK-Mrs.R SUGANYA -AP Page 25


23UBCAC43/23UCSCC43 – PROGRAMMING IN JAVA UNIT 3

o FileInputStream, FileOutputStream: For reading and writing binary


data.
o BufferedInputStream, BufferedOutputStream: For efficient reading
and writing of binary data.
 Character Stream Classes:
o FileReader, FileWriter: For reading and writing text (characters).
o BufferedReader, BufferedWriter: For efficient reading and writing of
text.
 Console I/O:
o System.out.print(), System.out.println(): For writing to the console.
o Scanner, BufferedReader: For reading user input from the console.
 File Handling:
o FileReader, FileWriter, BufferedReader, BufferedWriter: For reading
and writing files.
Java I/O is crucial for any real-world application that needs to interact with the
outside world (files, networks, databases, etc.). The choice between byte and
character streams depends on whether you are working with binary data or text
data.

DEPARTMENT OF COMPUTRE SCIENCE –RAAK-Mrs.R SUGANYA -AP Page 26

You might also like