You are on page 1of 21

Thread Life cycle:

A thread is an independent path of execution within a program. Many threads can run concurrently
within a program. Every thread in java is created and controlled by java.lang.Thread class.

Thread is a light-weight sub process, the smallest unit of processing.. Threads share the same address
space and therefore can share both data and code.

Threads are independent. If there occurs exception in one thread, it doesn’t affect other threads.

The life cycle of the thread in java is controlled by JVM. The java thread states are as follows:

1. New
2. Runnable
3. Running
4. Non-Runnable (Blocked)
5. Terminated

1) New

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

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.

Creation of threads

There are two ways to create a thread:

1. By extending Thread class

2. By implementing Runnable interface.

Thread class:

The first way to create a thread is to 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..
Program:

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.By Implementing Runnable Interface:


The easiest way to create a thread is to create a class that implements the Runnable interface.
Runnable abstracts a unit of executable code. You can construct a thread on any object that
implements Runnable. To implement Runnable, a class need only implement a single method called
run( ), which is declared like this:
public void run( )// define the code that constitutes the new thread.

After you create a class that implements Runnable, you will instantiate an object of type Thread from
within that class. Thread defines several constructors

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.
Program:
class Multi3 implements Runnable
{  
public void run()
{  
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…

Thread Synchronization:

If multiple threads are simultaneously trying to access the same resource strange results may occur.
To overcome them java synchronization is used. The operations performed on the resource must be
synchronized.
Monitor is the key to synchronization. A monitor is an object that is used as a mutually exclusive
lock.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 (other threads are waiting at that time) .

Code can be synchronized in two ways:

1. Using synchronized Methods


2. Using synchronized Statement

1. Using synchronized Methods :

synchronized void update()

- -- -

When as method is declared as synchronized, java creates a monitor and hands it over to the thread
that calls the method first time. As long as the thread holds the monitor no other thread can enter
the synchronized section of code.
Example:
class Table
{
synchronized void printTable(int n)
{//synchronized method
for(int i=1;i<=5;i++)
{
System.out.println(n*i);
try
{
Thread.sleep(400);
}catch(Exception e){System.out.println(e);}
}
}
}
class MyThread1 extends Thread{
Table t;
MyThread1(Table t){
this.t=t;
}
public void run(){
t.printTable(5);
}
}
class MyThread2 extends Thread{
Table t;
MyThread2(Table t){
this.t=t;
}
public void run(){
t.printTable(100);
}
}
public class TestSynchronization2{
public static void main(String args[]){
Table obj = new Table();//only one object
MyThread1 t1=new MyThread1(obj);
MyThread2 t2=new MyThread2(obj);
t1.start();
t2.start();
}
}

Output: 5
10
15
20
25
100
200
300
400
500

2. Using synchronized Statement:

This is the general form of the synchronized statement:

synchronized(objRef)

{
// statements to be synchronized
}

objRef is a reference to the object being synchronized. A synchronized block ensures that a call to
a synchronized method that is a member of objRef’s class occurs only after the current thread has
successfully entered objRef’s monitor.

Ex:
class Table{  
 void printTable(int n){  
   synchronized(this){//synchronized block  
     for(int i=1;i<=5;i++){  
      System.out.println(n*i);  
      try{  
       Thread.sleep(400);  
      }catch(Exception e){System.out.println(e);}  
     }  
   }  
 }//end of the method  
}  
  
class MyThread1 extends Thread{  
Table t;  
MyThread1(Table t){  
this.t=t;  
}  
public void run(){  
t.printTable(5);  
}  
  
}  
class MyThread2 extends Thread{  
Table t;  
MyThread2(Table t){  
this.t=t;  
}  
public void run(){  
t.printTable(100);  
}  
}  
  public class TestSynchronizedBlock1{  
public static void main(String args[]){  
Table obj = new Table();//only one object  
MyThread1 t1=new MyThread1(obj);  
MyThread2 t2=new MyThread2(obj);  
t1.start();  
t2.start();  
}  
}  
Output: 5
10
15
20
25
100
200
300
400
500

Priority of a Thread (Thread Priority):


Each thread have a priority. Priorities are represented by a number between 1 and 10. In most cases,
thread schedular schedules the threads according to their priority (known as preemptive scheduling).
But it is not guaranteed because it depends on JVM specification that which scheduling it chooses.
3 constants defiend in Thread class:
 public static int MIN_PRIORITY
 public static int NORM_PRIORITY
 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.
Example:
class TestMultiPriority1 extends Thread{  
 public void run()
{  
   System.out.println("running thread name is:"+Thread.currentThread().getName());  
   System.out.println("running thread priority is:"+Thread.currentThread().getPriority());  
    }  
 public static void main(String args[])
{  
  TestMultiPriority1 m1=new TestMultiPriority1();  
  TestMultiPriority1 m2=new TestMultiPriority1();  
  m1.setPriority(Thread.MIN_PRIORITY);  
  m2.setPriority(Thread.MAX_PRIORITY);  
  m1.start();  
  m2.start();  
    }  
}     
Output: running thread name is:Thread-0
running thread priority is:10
running thread name is:Thread-1
running thread priority is:1

Inter-thread communication:

To avoid polling, Java includes an elegant interprocess communication mechanism via


the wait( ), notify( ), and notifyAll( ) methods. These methods are implemented as final
methods in Object, so all classes have them. All three methods can be called only from
within a synchronized context. Although conceptually advanced from a computer science
perspective, the rules for using these methods are actually quite simple:

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( ) or notifyAll( ).
• notify( )------ wakes up a thread that called wait( ) on the same object.
• notifyAll( )-------- wakes up all the threads that called wait( ) on the same object. One of
the threads will be granted access.

These methods are declared within Object, as shown here:


final void wait( ) throws InterruptedException
final void notify( )
final void notify All( )

producer-consumer problem:

In computing, the producer–consumer problem (also known as the bounded-buffer problem) is a


classic example of a multi-process synchronization problem. The problem describes two processes,
the producer and the consumer, which share a common, fixed-size buffer used as a queue.
 The producer’s job is to generate data, put it into the buffer, and start again.
 At the same time, the consumer is consuming the data (i.e. removing it from the buffer), one
piece at a time.
Problem
To make sure that the producer won’t try to add data into the buffer if it’s full and that the consumer
won’t try to remove data from an empty buffer.
Solution 
The producer is to either go to sleep or discard data if the buffer is full. The next time the consumer
removes an item from the buffer, it notifies the producer, who starts to fill the buffer again. In the
same way, the consumer can go to sleep if it finds the buffer to be empty. The next time the producer
puts data into the buffer, it wakes up the sleeping consumer.

Example:
class Q {
int n;
boolean valueSet = false;
synchronized int get() {
while(!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) {

while(valueSet)
try {
wait();
} 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[]) {
Q q = new Q();
new Producer(q);
new Consumer(q);
System.out.println("Press Control-C to stop.");
}
}
Unit-4

IO Streams
Java performs I/O through 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.
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.
Byte Stream Classes:
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.
These classes define several key methods. Two most important are

 read() : reads byte of data.


 write() : Writes byte of data.

Character Stream Classes


Character stream is also defined by using two abstract class at the top of hierarchy, they are Reader
and Writer.These abstract classes handle Unicode character streams. Java has several concrete
subclasses of each of these
The abstract classes Reader and Writer define several key methods that the other stream classes
implement.

Two of the most important methods are read( ) and write( ), which read and write characters of data,
respectively.

Each has a form that is abstract and must be overridden by derived stream classes.

Reading Console Input


We use the object of BufferedReader class to take inputs from the keyboard.

Reading Input Characters


To read a character from a BufferedReader we will use int read() throws IOException. Each time that
read() is called, it reads a character from the input stream and returns it as an integer value. It returns
-1 when the end of the stream is encountered. If there goes something wrong it can throw an
IOException. The following program demonstrates read() by reading characters from the console until
the user types a 'q'. Notice that any I/O exceptions that might be generated are simply thrown out of
main(). Such an approach is common when reading from the console, but you can handle these types
of errors yourself, if you chose.
program:
// BufferedReader to read characters from the console.
import java.io.*;
class BufferedReaderCharDemo
{
public static void main(String args[]) throws IOException
{
char c;
BufferedReader br = new
BufferedReader(new InputStreamReader(System.in));
System.out.println("Enter characters, press 'q' to quit.");
// read characters
do
{
c = (char) br.read();
System.out.println(c);
} while(c != 'q');
}
}
 

OUTPUT
D:\JavaPrograms>javac BufferedReaderCharDemo.java
D:\JavaPrograms>java BufferedReaderCharDemo
Enter characters, press 'q' to quit.
krishanq
k
r
i
s
h
a
n
q

Reading Input Strings


To read a string from the keyboard we use String readLine() throws IOException that is a member of
the BufferedReader class. As you can see, it returns a String object. The following program
demonstrates BufferedReader and the readLine() method; the program reads and displays lines of text
until you enter the word "stop":
// Reading string from console.
import java.io.*;
class BufferedReaderStringDemo
{
public static void main(String args[]) throws IOException
{

// create a BufferedReader using System.in


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
D:\JavaPrograms>javac BufferedReaderStringDemo.java
D:\JavaPrograms>java BufferedReaderStringDemo
Enter lines of text.
Enter 'stop' to quit.
This is a String
This is a String
stop
stop

Writing console output:

Console output is most easily accomplished with print( ) and println( ), described
earlier,which are used in most of the examples in this book. These methods are
defined by the class PrintStream (which is the type of object referenced by
System.out). Even though System.out is a byte stream, using it for simple program
output is still acceptable. However,a character-based alternative is described in the
next section.
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. The simplest form of write( ) defined by PrintStream is shown here:
void write(int byteval)
This method writes the byte specified by byteval. Although byteval is declared as an
integer,only the low-order eight bits are written
The PrintWriter Class:
For realworld programs, the recommended method of writing to the console when
using Java is through a PrintWriter stream. PrintWriter is one of the character-
based classes. Using a character-based class for console output makes
internationalizing your program easier.
PrintWriter(OutputStream outputStream, boolean flushingOn)
Here, outputStream is an object of type OutputStream, and flushingOn controls
whether Java flushes the output stream every time a println( ) method (among others)
is called. If flushingOn is true, flushing automatically takes place. If false, flushing is
not automatic.
Syntax:
PrintWriter pw = new PrintWriter(System.out, true);

// Demonstrate PrintWriter
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);
}
}

Applet architecture:

AWT-based applets are subclasses of Applet. Applets are not stand-alone programs.
Instead,they run within either a web browser or an applet viewer.
Execution of an applet does not begin at main( ). Output to your applet’s window is
not performed by System.out.println( ). Rather, in an AWT-based applet, output is
handled with various AWT methods, such as drawString( ), which outputs a string to
a specified X,Y location. Input is also handled differently than in a console
application.
Applet is a special type of program that is embedded in the webpage to generate the
dynamic content. 

Advantages:

o It works at client side so less response time.


o Secured
o It can be executed by browsers running under many platforms, including
Linux, Windows, Mac Os etc.

Life cycle of an applet:

Applet class provides all necessary support for applet execution, such as initializing
and destroying of applet. It also provide methods that load and display images and
methods that load and play audio clips. It provides 4 life cycle methods of applet.
init(): The init() method is the first method to execute when the applet is executed.
Variable declaration and initialization operations are performed in this method.
 start(): The start() method contains the actual code of the applet that should run. The
start() method executes immediately after the init() method. It also executes whenever
the applet is restored, maximized or moving from one tab to another tab in the
browser.
 stop(): The stop() method stops the execution of the applet. The stop() method
executes when the applet is minimized or when moving from one tab to another in the
browser.
 destroy(): The destroy() method executes when the applet window is closed or when
the tab containing the webpage is closed. stop() method executes just before when
destroy() method is invoked. The destroy() method removes the applet object from
memory.
 paint(): The paint() method is used to redraw the output on the applet display area.
The paint() method executes after the execution of start() method and whenever the
applet or browser is resized.
ex:

import java.awt.*;
import java.applet.*;
/* <applet code="MyApplet.class" width=200 height=200>
</applet> */
public class MyApplet extends Applet
{
public void init()
{
System.out.println("Applet initialized");
}
public void start()
{
System.out.println("Applet execution started");
}
public void stop()
{
System.out.println("Applet execution stopped");
}
public void paint(Graphics g)
{
System.out.println("Painting...");
}
public void destroy()
{
System.out.println("Applet destroyed");
}
}
output:

Applet initialized
Applet execution started
Painting…
Painting…
Applet execution stopped
Applet destroyed

Read a file contents:

import java.io.FileNotFoundException;

import java.io.FileReader;

import java.io.IOException;

class ReadFile

public static void main(String[] args) throws IOException

// variable declaration

int ch;

// check if File exists or not

FileReader fr=null;

try

fr = new FileReader("output.txt");

catch (FileNotFoundException fe)

{
System.out.println("File not found");

// read from FileReader till the end of file

while ((ch=fr.read())!=-1)

System.out.print((char)ch);

// close the file

fr.close();

Write the contents to a file

import java.io.FileWriter;

import java.io.IOException;

class CreateFile

public static void main(String[] args) throws IOException

// Accept a string

String str = "File Handling in Java using "+

" FileWriter and FileReader";

System.out.println(str);

// attach a file to FileWriter

FileWriter fw=new FileWriter("output.txt");

// read character wise from string and write


// into FileWriter

for (int i = 0; i < str.length(); i++)

fw.write(str.charAt(i));

System.out.println("Writing successful");

//close the file

fw.close();

You might also like