0% found this document useful (0 votes)
465 views15 pages

UNIT 4 NOTES Oops

The document discusses how to create and manage threads in Java. It describes two ways to create threads by extending the Thread class or implementing the Runnable interface. It also explains the different states a thread can be in like new, runnable, blocked, waiting, timed waiting and terminated.

Uploaded by

Harendra Tomar
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)
465 views15 pages

UNIT 4 NOTES Oops

The document discusses how to create and manage threads in Java. It describes two ways to create threads by extending the Thread class or implementing the Runnable interface. It also explains the different states a thread can be in like new, runnable, blocked, waiting, timed waiting and terminated.

Uploaded by

Harendra Tomar
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/ 15

➔Creating Threads

There are two ways to creates thread in java:


1. Creating own class which is extending to parent Thread class
2. Implementing the Runnable interface.
Creating own class which is extending to parent Thread class
class MyThread extends Thread
{
public void run()
{
System.out.println("Thread is running created by extending
Thread class");
}
}
class Myclass
{
public static void main(String[] args)
{
MyThread myThread = new MyThread();
myThread.start();
Sytem.out.println(“In main Thread”);
}
}
Implementing the Runnable interface

class MyThread implements Runnable


{
public void run()
{
System.out.println("Thread is running created by implanting
Runnable Interface");
}
}
class Myclass
{
public static void main(String[] args)
{
MyThread ob=new MyThread();
Thread myThread = new Thread(ob);
myThread.start();
System.out.println(“In main Thread”);
}
}

➔Lifecycle and States of a Thread in Java


A thread in Java at any point of time exists in any one of the following states. A thread lies
only in one of the shown states at any instant:
1. New
2. Runnable
3. Blocked
4. Waiting
5. Timed Waiting
6. Terminated
The diagram shown below represents various states of a thread at any instant in time.

Life Cycle of a thread


1. New Thread: When a new thread is created, it is in the new state. The thread has
not yet started to run when the thread is in this state. When a thread lies in the new
state, its code is yet to be run and hasn’t started to execute.
2. Runnable State: A thread that is ready to run is moved to a runnable state. In this
state, a thread might actually be running or it might be ready to run at any instant of
time. It is the responsibility of the thread scheduler to give the thread, time to run.
A multi-threaded program allocates a fixed amount of time to each individual thread.
Each and every thread runs for a short while and then pauses and relinquishes the
CPU to another thread so that other threads can get a chance to run. When this
happens, all such threads that are ready to run, waiting for the CPU and the currently
running thread lie in a runnable state.
3. Blocked/Waiting state: When a thread is temporarily inactive, then it’s in one of
the following states:
• Blocked
• Waiting
4. Timed Waiting: A thread lies in a timed waiting state when it calls a method with a
time-out parameter. A thread lies in this state until the timeout is completed or until a
notification is received. For example, when a thread calls sleep or a conditional wait,
it is moved to a timed waiting state.
5. Terminated State: A thread terminates because of either of the following reasons:
• Because it exits normally. This happens when the code of the thread has
been entirely executed by the program.
• Because there occurred some unusual erroneous event, like segmentation
fault or an unhandled exception.

➔Getting the Thread States in Java

In Java, to get the current state of the thread, use Thread.getState() method to get the current
state of the thread. Java provides java.lang.Thread.State class that defines the ENUM constants
for the state of a thread, as a summary of which is given below:
A thread state. A thread can be in one of the following states:

• NEW
A thread that has not yet started is in this state.
• RUNNABLE
A thread executing in the Java virtual machine is in this state.
• BLOCKED
A thread that is blocked waiting for a monitor lock is in this state.
• WAITING
A thread that is waiting indefinitely for another thread to perform a particular action is in
this state.
• TIMED_WAITING
A thread that is waiting for another thread to perform an action for up to a specified waiting
time is in this state.
• TERMINATED
A thread that has exited is in this state.

A thread can be in only one state at a given point in time. These states are virtual machine states
which do not reflect any operating system thread states.

➔Methods of Thread class:

Now let us do discuss all the methods of this class are illustrated as follows:

currentThread() Returns a reference to the currently executing thread object

getId() Returns the identifier of this Thread

getName() Returns this thread’s name

getPriority() Returns this thread’s priority

getState() Returns the state of this thread

interrupt() Interrupts this thread

interrupted() Tests whether the current thread has been interrupted

isAlive() Tests if this thread is alive

isDaemon() Tests if this thread is a daemon thread

join() Waits for this thread to die

join(long millis) Waits at most millis milliseconds for this thread to die
If this thread was constructed using a separate Runnable run
run() object, then that Runnable object’s run method is called;
otherwise, this method does nothing and returns

setDaemon(boolean
Marks this thread as either a daemon thread or a user thread
on)

setName(String
Changes the name of this thread to be equal to the argument name.
name)

setPriority(int
Changes the priority of this thread
newPriority)

Causes the currently executing thread to sleep (temporarily cease


sleep(long millis) execution) for the specified number of milliseconds, subject to the
precision and accuracy of system timers and schedulers

Causes this thread to begin execution; the Java Virtual Machine


start()
calls the run method of this thread

Returns a string representation of this thread, including the


toString()
thread’s name, priority, and thread group

A hint to the scheduler that the current thread is willing to yield its
yield()
current use of a processor

Differences between wait() and join() methods in Java


The wait() and join() methods are used to pause the current thread. The wait() is used in with
notify() and notifyAll() methods, but join() is used in Java to wait until one thread finishes its
execution. wait() is mainly used for shared resources, a thread notifies other waiting thread when
a resource becomes free. On the other hand join() is used for waiting a thread to die.
1. yield() Method
The yield() basically means that the thread is not doing anything particularly important and if
any other threads or processes need to be run, they should run. Otherwise, the current thread will
continue to run.
• Once a thread has executed the yield method and there are many threads with the
same priority is waiting for the processor, then we can’t specify which thread will get
the execution chance first.
• The thread which executes the yield method will enter in the Runnable state from
Running state.
2. sleep() Method
This method causes the currently executing thread to sleep for the specified number of
milliseconds, subject to the precision and accuracy of system timers and schedulers.
3. join() Method
If join() is called on a Thread instance, the currently running thread will block until the Thread
instance has finished executing. The join() method waits at most this many milliseconds for this
thread to die. A timeout of 0 means to wait forever.

➔Priorities in threads
It is a concept where each thread is having a priority which in layman’s language one can say
every object is having priority here which is represented by numbers ranging from 1 to 10.
• The default priority is set to 5 as excepted.
• Minimum priority is set to 1.
• Maximum priority is set to 10.
Here 3 constants are defined in it namely as follows:
1. public static int NORM_PRIORITY
2. public static int MIN_PRIORITY
3. public static int MAX_PRIORITY

class ThreadDemo extends Thread


{
public void run()
{
System.out.println("Inside run method");
}

public static void main(String[] args)


{

ThreadDemo t1 = new ThreadDemo();


ThreadDemo t2 = new ThreadDemo();
ThreadDemo t3 = new ThreadDemo();

System.out.println("t1 thread priority : "+ t1.getPriority());

System.out.println("t2 thread priority : "+ t2.getPriority());

System.out.println("t3 thread priority : "+ t3.getPriority());


t1.setPriority(2);
t2.setPriority(5);
t3.setPriority(8);

// t3.setPriority(21); will throw IllegalArgumentException

System.out.println("t1 thread priority : "+ t1.getPriority());

System.out.println("t2 thread priority : "+ t2.getPriority());

System.out.println("t3 thread priority : "+ t3.getPriority());

System.out.println("Currently Executing Thread :"+Thread.currentThread().getName());

System.out.println("Main thread priority : "+ Thread.currentThread().getPriority());

Thread.currentThread().setPriority(10);

System.out.println("Main thread priority : "+ Thread.currentThread().getPriority());


}
}

➔Java – Thread Synchronization


Java programming language provides a very handy way of creating threads and synchronizing
their task by using synchronized blocks or method. You keep shared resources within this block
or method.
To synchronize the action of multiple threads and make sure that only one thread can access the
resource at a given point in time, we can use either synchronized block or method.
class Table
{
synchronized void printTable(int n)
{
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 TestSync2


{
public static void main(String args[])
{
Table obj = new Table();
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
➔Java - Interthread Communication
Interthread communication is important when you develop an application where two or more
threads exchange some information.
There are three simple methods and a little trick which makes thread communication possible. All
the three methods are listed below −
public void wait()
Causes the current thread to wait until another thread invokes the notify().
public void notify()
Wakes up a single thread that is waiting on this object's monitor
public void notifyAll()
Wakes up all the threads that called wait( ) on the same object
Example:-
class Chat
{
boolean flag = false;

public synchronized void Question(String msg)


{
if (flag)
{
try {
wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}

System.out.println(msg);
flag = true;
notify();
}

public synchronized void Answer(String msg)


{
if (!flag)
{
try {
wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}

System.out.println(msg);
flag = false;
notify();
}
}

class T1 extends Thread


{
Chat m;
String[] s1 = { "Hi", "How are you ?", "I am also doing fine!" };

public T1(Chat m1)


{
m = m1;
}

public void run()


{
for (int i = 0; i < s1.length; i++)
{
m.Question(s1[i]);
}
}
}

class T2 extends Thread


{
Chat m;
String[] s2 = { "Hello", "I am good, what about you?", "Great!" };

public T2(Chat m2)


{
this.m = m2;
}

public void run()


{
for (int i = 0; i < s2.length; i++)
{
m.Answer(s2[i]);
}
}
}
public class TestThread1
{
public static void main(String[] args)
{
Chat m = new Chat();
T1 ob1=new T1(m);
T2 ob2=new T2(m);

ob1.start();
ob2.start();
}
}

OUTPUT:
Hi,
Hello
How are you ?
I am good, what about you?
I am also doing fine!
Great
➔Daemon Thread
Daemon thread in Java is a low-priority thread that performs background operations such
as garbage collection, finalizer, Action Listeners, Signal dispatches, etc.
Daemon thread in Java is also a service provider thread that helps the user thread. Its life is at the
mercy of user threads; when all user threads expire, JVM immediately terminates this thread.
In simple words, we can say that it provides services to user threads for background-supporting
tasks. Daemon thread in Java has no role in life other than to serve user threads.
➔Java Generics
Java Generics allows us to create a single class, interface, and method that can be used with
different types of data (objects).
This helps us to reuse our code.
Generics Work Only with Reference Types:
When we declare an instance of a generic type, the type argument passed to the type parameter
must be a reference type. We cannot use primitive data types like int, char.
Generic Classes:
A generic class is implemented exactly like a non-generic class. The only difference is that it
contains a type parameter section. There can be more than one type of parameter, separated by a
comma. The classes, which accept one or more parameters, are known as parameterized classes or
parameterized types.
Example:-
class Test<T>
{
T ob;
Test(T obj)
{
ob = obj;
}
public T myfun()
{
return ob;
}
}

class Generic1
{
public static void main(String[] args)
{

Test<Integer> ob1 = new Test<Integer>(15);

System.out.println(ob1.myfun());

Test<String> ob2 = new Test<String>("Java Programming");

System.out.println(ob2.myfun());
}
}

Generic Functions:
We can also write generic functions that can be called with different types of arguments based on
the type of arguments passed to the generic method. The compiler handles each method.
Example:-
class GenericM
{
static <T> void myfun(T ob)
{
System.out.println(ob.getClass().getName());
System.out.println(ob);
}

public static void main(String[] args)


{

myfun(11);
myfun("Java");
myfun(1.0);
}
}

➔Bounded Types with Generics in Java


There may be times when you want to restrict the types that can be used as type arguments in a
parameterized type. For example, a method that operates on numbers might only want to accept
instances of Numbers or their subclasses. This is what bounded type parameters are for.
Syntax
<T extends superClassName>

Note that, in this context, extends is used in a general sense to mean either “extends” (as in
classes). Also, This specifies that T can only be replaced by superClassName or subclasses of
superClassName. Thus, a superclass defines an inclusive, upper limit.
Example:-
class Bound<T extends A>
{

private T ob;

public Bound(T obj)


{
ob = obj;
}

public void myfun()


{
ob.displayClass();
}
}

class A
{
public void displayClass()
{
System.out.println("Inside super class A");
}
}

class B extends A
{
public void displayClass()
{
System.out.println("Inside sub class B");
}
}

class C extends A
{
public void displayClass()
{
System.out.println("Inside sub class C");
}
}

public class BoundedClass


{
public static void main(String a[])
{

Bound<C> bec = new Bound<C>(new C());


bec.myfun();

Bound<B> beb = new Bound<B>(new B());


beb.myfun();

Bound<A> bea = new Bound<A>(new A());


bea.myfun();

//Will throw Exception in compile time


//Bound<String> bea1 = new Bound<String>(new A());
//bea1.myfun();

}
}

Multiple Bounds
Java Generics supports multiple bounds also, i.e., In this case, A can be an interface or class. If
A is class, then B and C should be interfaces. We can’t have more than one class in multiple
bounds.
Syntax:
<T extends superClassName & Interface>
A type variable with multiple bounds is a subtype of all the types listed in the bound. If one of the
bounds is a class, it must be specified first.
Example:-
class Bound<T extends A & B>
{

private T ob;

public Bound(T obj)


{
ob = obj;
}
public void myfun()
{
ob.displayClass();
}
}

interface B
{
public void displayClass();
}

class A implements B
{
public void displayClass()
{
System.out.println("Inside super class A");
}
}

class C extends A
{
public void displayClass()
{
System.out.println("Inside super class C");
}
}

public class BoundedClass1


{
public static void main(String a[])
{

Bound<A> bea = new Bound<A>(new A());


bea.myfun();

Bound<C> bea1 = new Bound<C>(new C());


bea1.myfun();

}
}

You might also like