You are on page 1of 58

CS8392 OBJECT ORIENTED PROGRAMMING

UNIT IV MULTITHREADING AND GENERIC PROGRAMMING

Differences between multi-threading and multitasking, thread life cycle,


creating threads, synchronizing threads, Inter-thread communication, daemon
threads, thread groups. Generic Programming – Generic classes – generic
methods – Bounded Types – Restrictions and Limitations.
Multithreading
Multithreading is a Java feature that allows concurrent execution of two or more parts of a program for
maximum utilization of CPU. Each part of such program is called a thread and each thread defines a separate
path of execution. So, threads are light-weight process. Multithreading is a specialized form of multitasking.
Multitasking
Multitasking is a process of executing multiple tasks simultaneously. We use multitasking to utilize the CPU.
In multitasking, each process has a different resource and memory and does not share it. Multitasking can be
achieved in two ways:
1. Process-based Multitasking (Multiprocessing)
More than 1 process runs concurrently. 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 register, memory
maps, updating lists, etc.
Example
Executing an excel spreadsheet while running a word processor.
2. Thread-based multitasking: More than 1 thread executes concurrently. A thread executes different parts
of the same program. Threads share the same address space. A thread is lightweight. Cost of communication
between the thread is low.
Example
Formatting a text in a word processor and printing it at the same time. Even though each thread has a
different execution path for the same process, all threads share the same resource and memory.
The Java Thread Model
 The Java run-time system depends on threads for many things, and all the class libraries are
designed with multithreading.
 A thread is a lightweight subprocess, the smallest unit of processing. It is a separate path of
execution. Threads are independent. 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.
Thread life cycle
A thread goes through various stages in its life cycle. For example, a thread is born, started, runs, and
then dies. A thread lies only in one of the shown states at any instant:
 New
 Runnable
 Running
 Non-Runnable (Blocked)
 Terminated
1. New
When a new thread is created, it is in the new state. The thread has not yet started to run. 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. It is the duty of the thread scheduler to provide the thread time to run, i.e., moving
the thread the running state.
3. Running
The thread is in running state if the thread scheduler has selected it. When the thread gets the CPU, it moves
from the runnable to the running state
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. A thread reaches the termination state
because of the following reasons:
 When a thread has finished its job, then it exists or terminates normally.
 Abnormal termination: It occurs when some unusual events such as an unhandled exception or
segmentation fault.
A terminated thread means the thread is no more in the system. In other words, the thread is dead, and there is
no way one can respawn (active after kill) the dead thread.
Thread Class and Runnable Interface
 Java’s multithreading system is built upon the Thread class, its methods, and its companion
interface, Runnable. To create a new thread, program will either
extend Thread or implement the Runnable interface.
 The Thread class defines several methods that help manage threads. The table below displays the
same:
Method  Meaning
getName Obtain thread’s name
getPriority Obtain thread’s priority
isAlive Determine if a thread is still running
join Wait for a thread to terminate
run Entry point for the thread
sleep Suspend a thread for a period of time
start Start a thread by calling its run method
The Main Thread
When a Java program starts up, one thread begins running immediately. This is usually called the
main thread of a program, because it is the one that is executed when our program begins. The main
thread is important for two reasons:
 It is the thread from which other “child” threads will be spawned.
 Often, it must be the last thread to finish execution because it performs various shutdown actions.
Although the main thread is created automatically when your program is started, it can be controlled
through a Thread object. To do so, It is possible to obtain a reference of main thread by calling the
method currentThread( ), which is a public static member of Thread. Its general form is
static Thread currentThread( )
This method returns a reference to the thread in which it is called. Once have a reference to the main
thread, we can control it just like any other thread.
Example
public class Javathread
{
public static void main(String[] args)
{
Thread t = Thread.currentThread( );
System.out.println("Current thread: " + t);
// change the name of the thread
System.out.println("Name of current thread: " + t.getName());
t.setName("My Thread");
System.out.println("After name change: " + t);
}
}
Output
Current thread: Thread[main,5,main]
Name of current thread: main
After name change: Thread[My Thread,5,main]
 In this program, a reference to the current thread (the main thread, in this case) is obtained by
calling currentThread( ), and this reference is stored in the local variable t. Next, the program
displays information about the thread.
 This displays, in order: the name of the thread, its priority, and the name of its group.
 By default, the name of the main thread is main. Its priority is 5, which is the default value, and
main is also the name of the group of threads to which this thread belongs.
 A thread group is a data structure that controls the state of a collection of threads as a whole.
 Set the name of a thread by using setName( ). Obtain the name of a thread by calling getName( ).
These methods are members of the Thread class.
Creating a Thread
There are two ways to create a thread:
 By extending Thread class
 By implementing Runnable interface.
i) Implementing Runnable Interface
 The easiest way to create a thread is to create a class that implements the Runnable interface.
 To implement Runnable interface, a class need only implement a single method called run( ), which
is declared like this:
public void run( )
 Inside run( ), we will define the code that constitutes the new thread
Example
public class MyClass implements Runnable
{
public void run( )
{
System.out.println("MyClass running");
}
}
To execute the run( ) method by a thread, pass an instance of MyClass to a Thread in its
constructor(A constructor in Java is a block of code similar to a method that’s called when an
instance of an object is created).
Thread t1 = new Thread(new MyClass ( ));
t1.start( );
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.
Example
public class Javathread implements Runnable
{
public void run( )
{
System.out.println("Javathread is running...");
}
public static void main(String args[ ])
{
Javathread m1=new Javathread( );
Thread t1 =new Thread(m1);
t1.start( );
}
}
ii) Extending Java Thread
The second 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. Here is the
preceding program rewritten to extend Thread.
Example
public class MyClass extends Thread
{
public void run( )
{
System.out.println("MyClass running");
}
}
To create and start the above thread you can do like this:
MyClass t1 = new MyClass ( );
t1.start( );
Example
public class Javathread extends Thread
{
public void run( )
{
System.out.println("Javathread is running...");
}
public static void main(String args[ ])
{
Javathread t1=new Javathread( );
t1.start( );
}
}
Example
class NewThread implements Runnable
{
String name; // name of thread
Thread t;
NewThread(String threadname)
{
name = threadname;
t=new Thread(this, name);
System.out.println("New thread: " + t);
}
public void run( ) {
try {
for(int i = 5; i > 0; i--)
{
System.out.println(name + ": " + i);
Thread.sleep(5000);
}}
catch (InterruptedException e)
{
System.out.println(name + "Interrupted");
}
System.out.println(name + " exiting.");
} }
public class Javathread
{
public static void main(String args[])
{
Thread t1 =new Thread(new NewThread("One"));
t1.start( );
Thread t2 =new Thread(new NewThread("Two"));
t2.start( );
Thread t3 =new Thread(new NewThread("Three"));
t3.start( );
try
{
// wait for other threads to end
Thread.sleep(50000);
}
catch (InterruptedException e)
{
System.out.println("Main thread Interrupted");
}
System.out.println("Main thread exiting.");
}
}
Output
New thread: Thread[One,5,main]
New thread: Thread[Two,5,main]
One: 5
New thread: Thread[Three,5,main]
Two: 5
Three: 5
One: 4
Two: 4
Three: 4
One: 3
Three: 3
Two: 3
One: 2
Two: 2
Three: 2
Three: 1
One: 1
Two: 1
One exiting.
Two exiting.
Three exiting.
Main thread exiting.
Using isAlive( ) and join( )
 Sometimes one thread needs to know when other thread is terminating.
 In java, isAlive( ) and join( ) are two different methods that are used to check whether a thread has
finished its execution or not.
 The isAlive( ) method returns true if the thread upon which it is called is still running otherwise it
returns false.

final boolean isAlive( )


 But, join( ) method is used more commonly than isAlive( ). This method waits until the thread on which it
is called terminates.
final void join( ) throws InterruptedException
 Using join( ) method, we tell our thread to wait until the specified thread completes its execution. There
are overloaded versions of join( ) method, which allows us to specify time for which you want to wait for
the specified thread to terminate.
final void join(long milliseconds) throws InterruptedException
Example
class Javathread extends Thread
{
public void run()
{
try
{
Thread.sleep(1000);
System.out.println("Is run() method isAlive "+Thread.currentThread().isAlive( ));
}
catch (InterruptedException ie)
{
} }
public static void main(String[] args)
{
Javathread t1 = new Javathread();
System.out.println("Before starting thread isAlive: "+t1.isAlive( ));
t1.start( );
System.out.println("After starting thread isAlive: "+t1.isAlive( ));
}
}
Before starting thread isAlive: false
After starting thread isAlive: true
Is run() method isAlive true
Example of thread without join( ) method
If we run a thread without using join( ) method then the execution of thread cannot be predict. Thread scheduler schedules the execution of
thread.
class Javathread extends Thread {
public void run( )
{
System.out.println("r1 ");
try {
Thread.sleep(500);
}
catch(InterruptedException ie){ }
System.out.println("r2 ");
}
public static void main(String[ ] args) {
Javathread t1=new Javathread();
Javathread t2=new Javathread();
t1.start( );
t2.start( );
}}
Output
r1
r1
r2
r2
Example of thread with join( ) method
In this example, we are using join( ) method to ensure that thread finished its execution before
starting other thread. It is helpful when we want to executes multiple threads based on our
requirement.
Example
class Javathread extends Thread
{
public void run()
{
System.out.println("r1 ");
try
{
Thread.sleep(1000);
}
catch(InterruptedException ie){ }
System.out.println("r2 ");
}
public static void main(String[] args)
{
Javathread t1=new Javathread( );
Javathread t2=new Javathread( );
t1.start( );
try
{
t1.join( ); //Waiting for t1 to finish
}catch(InterruptedException ie){}
t2.start( );
}
}
Output
r1
r2
r1
r2
Thread Priorities
 Each thread have a priority. Thread priorities are used by the thread scheduler to decide when each
thread should be allowed to run. In theory, higher-priority threads get more CPU time than lower-
priority threads.
 Priorities are represented by a number between 1 and 10. In most cases, thread schedular
schedules the threads according to their priority. But it is not guaranteed because it depends on
JVM specification that which scheduling it chooses.
3 constants defined 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.
 To set a thread’s priority, use the setPriority( ) method, which is a member of Thread. This is its
general form:
final void setPriority(int level)
 Here, level specifies the new priority setting for the calling thread
 Obtain the current priority setting by calling the getPriority( ) method of Thread, shown here:
final int getPriority( )
Example
class Javathread 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[ ])
{
Javathread m1=new Javathread( );
Javathread m2=new Javathread( );
m1.setPriority(Thread.MIN_PRIORITY);
m1.setName("Hai");
m2.setPriority(2);
m1.start( );
m2.start( );
} }
Output
Running thread name is:Hai
Running thread name is:Thread-1
Running thread priority is:1
Running thread priority is:2
Synchronizing Threads
 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. The process by which this is achieved is
called synchronization.
 Synchronization in Java is the capability to control the access of multiple threads to any shared
resource.
 Java Synchronization is better option where we want to allow only one thread to access the shared
resource.
 There are two types of thread synchronization
1. Mutual Exclusive
Synchronized method.
Synchronized block.
2. Cooperation (Inter-thread communication in java)
Mutual Exclusive
Mutual Exclusive helps keep threads from interfering with one another while sharing data. It can be
achieved by using the following three ways:
 By Using Synchronized Method
 By Using Synchronized Block
Key to synchronization is the concept of the monitor. 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. These other threads are said to be waiting for the monitor.
The problem without Synchronization
In this example, we are not using synchronization and creating multiple threads that are accessing display
method and produce the random output.
Example
class First {
public void display(String msg)
{
System.out.print ("["+msg);
try
{
Thread.sleep(1000);
}
catch(InterruptedException e)
{
e.printStackTrace( );
}
System.out.println ("]");
} }
Example
class Second extends Thread
{
String msg;
First fobj;
Second (First fp,String str)
{
fobj = fp;
msg = str;
}
public void run()
{
fobj.display(msg);
}
}
public class Javathread
{
public static void main(String args[])
{
First fnew = new First();
Second ss = new Second(fnew, "welcome");
Second ss1= new Second(fnew,"new");
Second ss2 = new Second(fnew, "programmer");
Output
[welcome[new[programmer]
]
]
In the above program, object fnew of class First is shared by all the three running threads(ss, ss1 and
ss2) to call the shared method(void display). Hence the result is nonsynchronized and such situation
is called Race condition..
i) Synchronized Method
 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.
 This is done by using keyword synchronized with display() method.
synchronized void display (String msg)
Example
class First
{
synchronized public void display(String msg)
{
System.out.print ("["+msg);
try
{
Thread.sleep(1000);
}
catch(InterruptedException e)
{
e.printStackTrace();
}
System.out.println ("]");
}
}
class Second extends Thread
{
String msg;
First fobj;
Second (First fp,String str)
{
fobj = fp;
msg = str;
}
public void run()
{
fobj.display(msg);
}
}
public class Javathread
{
public static void main(String args[])
{
First fnew = new First();
Second ss = new Second(fnew, "welcome");
Second ss1= new Second(fnew,"new");
Second ss2 = new Second(fnew, "programmer");
ss.start( );
ss1.start( );
ss2.start( );
}
}
Output
[welcome]
[programmer]
[new]
ii) Synchronized Block
 Synchronized block can be used to perform synchronization on any specific resource of the
method.
 Suppose we have 50 lines of code in our method, but we want to synchronize only 5 lines, in such
cases, we can use synchronized block.
 If we put all the codes of the method in the synchronized block, it will work same as the
synchronized method.
Syntax
synchronized (object reference expression) 
{     
  //code block     
}    
Example
In this example, we are using synchronized block that will make the display method available for
single thread at a time.
class First
{
public void display(String msg)
{
synchronized(this)
{
System.out.print ("["+msg);
try
{
Thread.sleep(1000);
}
catch(InterruptedException e)
{
e.printStackTrace();
}
System.out.println ("]");
}
}
}
class Second extends Thread
{
String msg;
First fobj;
Second (First fp,String str)
{
fobj = fp;
msg = str;
}
public void run()
{
fobj.display(msg);
}}
public class Javathread
{
public static void main(String args[])
{
First fnew = new First();
Second ss = new Second(fnew, "welcome");
Second ss1= new Second(fnew,"new");
Second ss2 = new Second(fnew, "programmer");
ss.start();
ss1.start();
ss2.start();
} }
Inter-thread Communication
Thread Pooling
 Polling is usually implemented by a loop that is used to check some condition repeatedly. Once the
condition is true, appropriate action is taken. This wastes CPU time. For example, consider the
classic queuing problem, where one thread is producing some data and another is consuming it. To
make the problem more interesting, suppose that the producer has to wait until the consumer is
finished before it generates more data. In a polling system, the consumer would waste many CPU
cycles while it waited for the producer to produce. Once the producer was finished, it would start
polling, wasting more CPU cycles waiting for the consumer to finish, and so on. Clearly, this
situation is undesirable.
 To avoid polling, Java includes an elegant interprocess communication mechanism
 Inter-thread communication or Co-operation is all about allowing synchronized threads to
communicate with each other.
 Cooperation (Inter-thread communication) is a mechanism in which a thread is paused running in
its critical section and another thread is allowed to enter (or lock) in the same critical section to be
executed. It is implemented by following methods of Object class:
wait( )
notify( )
notifyAll( )
 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
1. 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( ).
2. notify( ) wakes up a thread that called wait( ) on the same object.
3. notifyAll( ) wakes up all the threads that called wait( ) on the same object. One of the threads will
be granted access.
 wait( ) normally waits until notify( ) or notifyAll( ) is called
These methods are declared within Object, as shown here:
 final void wait( ) throws InterruptedException
 final void notify( )
 final void notify All( )
Example
class Customer
{
int amt=10000;
synchronized void withdraw(int amount)
{
System.out.println("going to withdraw...");
if(this.amt<amount)
{
System.out.println("Less balance; waiting for deposit...");
try
{
wait( );
}
catch(Exception e){}
}
this.amount-=amount;
System.out.println("withdraw completed...");
}
synchronized void deposit(int amount)
{
System.out.println("going to deposit...");
this.amount+=amount;
System.out.println("deposit completed... ");
notify( );
}
}
public class Interthread
{
public static void main(String[] args)
{
final Customer c=new Customer( );
new Thread( )
{
public void run( )
{
c.withdraw(15000);
}
}.start( );
new Thread( )
{
public void run( )
{
c.deposit(10000);
}
}.start( );
}
}
Output
going to withdraw...
Less balance; waiting for deposit...
going to deposit...
deposit completed...
withdraw completed...
Deadlock
Deadlock in Java is a part of multithreading. Deadlock can occur in a situation when a thread is waiting for an
object lock, that is acquired by another thread and second thread is waiting for an object lock that is acquired by
first thread. Since, both threads are waiting for each other to release the lock, the condition is called deadlock.
Example
public class Interthread
{
public static void main(String[] args)
{
final String resource1 = "ratan jaiswal";
final String resource2 = "vimal jaiswal";
// t1 tries to lock resource1 then resource2
Thread t1 = new Thread()
{
public void run()
{
synchronized (resource1)
{
System.out.println("Thread 1: locked resource 1");
try
{
Thread.sleep(1000);
}
catch (Exception e) {}

synchronized (resource2)
{
System.out.println("Thread 1: locked resource 2");
}
}
}
};
Thread t2 = new Thread( )
{
public void run( )
{
synchronized (resource2)
{
System.out.println("Thread 2: locked resource 2");
try
{
Thread.sleep(1000);
}
catch (Exception e) { }
synchronized (resource1)
{
System.out.println("Thread 2: locked resource 1");
}
}
}
};
t1.start( );
t2.start( );
}
}
Output
Thread 1: locked resource 1
Thread 2: locked resource 2
Continue running
Daemon Thread in Java
 Daemon thread in java is a service provider thread that provides services to the user thread. Its life
depend on the mercy of user threads i.e. when all the user threads dies, JVM terminates this thread
automatically.
 It provides services to user threads for background supporting tasks. It has no role in life than to
serve user threads.
 Its life depends on user threads.
 It is a low priority thread.
Example
Garbage collection thread is one of the system generated daemon thread that runs in background.
These threads run in the background to perform tasks such as garbage collection.
 The sole purpose of the daemon thread is that it provides services to user thread for background
supporting task. If there is no user thread, why should JVM keep running this thread. That is why JVM
terminates the daemon thread if there is no user thread.
Methods for Java Daemon thread by Thread class
The java.lang.Thread class provides two methods for java daemon thread.

No. Method Description


1) public void setDaemon(boolean status) Is used to mark the current thread as daemon thread or user thread.

2) public boolean isDaemon( ) Is used to check that current is daemon.

Example
public class Interthread extends Thread
{
public void run()
{
if(Thread.currentThread().isDaemon())
{//checking for daemon thread
System.out.println("daemon thread work");
}
else
{
System.out.println("user thread work");
}}
public static void main(String[ ] args)
{
Interthread t1=new Interthread( );//creating thread
Interthread t2=new Interthread( );
Interthread t3=new Interthread( );
t1.setDaemon(true);//now t1 is daemon thread
t1.start( );//starting threads
t2.start( );
t3.start( );
}
}
Output
daemon thread work
user thread work
user thread work
Thread Groups
 ThreadGroup is a class which is used for creating group of threads. This group of threads are in the
form of a tree structure, in which the initial thread is the parent thread.
 Java provides a convenient way to group multiple threads in a single object. In such way, we can
suspend, resume or interrupt group of threads by a single method call.
 Java thread group is implemented by java.lang.ThreadGroup class.
 A thread is allowed to access information about its own thread group, but it cannot access the
information about its thread group's parent thread group or any other thread groups.
Constructors of ThreadGroup class
There are only two constructors of ThreadGroup class.

Constructor Description
ThreadGroup(String name) creates a thread group with given name.
ThreadGroup(ThreadGroup parent, String name) creates a thread group with given parent group and
name.
Methods of ThreadGroup class
There are many methods in ThreadGroup class. A list of ThreadGroup methods are given below.

Modifier and Type Method Description


void checkAccess( ) This method determines if the currently running thread has
permission to modify the thread group.

int activeCount( ) This method returns an estimate of the number of active


threads in the thread group and its subgroups.

int activeGroupCount( ) This method returns an estimate of the number of active


groups in the thread group and its subgroups.

void destroy( ) This method destroys the thread group and all of its
subgroups.
int enumerate(Thread[ ] list) This method copies into the specified array every active
thread in the thread group and its subgroups.

int getMaxPriority( ) This method returns the maximum priority of the thread
group.

String getName( ) This method returns the name of the thread group.
ThreadGroup getParent( ) This method returns the parent of the thread group.
void interrupt( ) This method interrupts all threads in the thread group.
boolean isDaemon( ) This method tests if the thread group is a daemon thread
group.
void setDaemon(boolean daemon) This method changes the daemon status of the thread
group.
boolean isDestroyed( ) This method tests if this thread group has been destroyed.
void list( ) This method prints information about the thread group to
the standard output.
boolean parentOf(ThreadGroup g) This method tests if the thread group is either the thread
group argument or one of its ancestor thread groups.
void suspend( ) This method is used to suspend all threads in the thread
group.
void resume( ) This method is used to resume all threads in the thread
group which was suspended using suspend() method.
void setMaxPriority(int pri) This method sets the maximum priority of the group.
void stop( ) This method is used to stop all threads in the thread group.
String toString( ) This method returns a string representation of the Thread
group.
Example
public class Interthread implements Runnable
{
public void run( )
{
System.out.println(Thread.currentThread( ).getName( ));
}
public static void main(String[ ] args)
{
Interthread runnable = new Interthread( );
ThreadGroup tg1 = new ThreadGroup("Parent ThreadGroup");
Thread t1 = new Thread(tg1, runnable,"one");
t1.start( );
Thread t2 = new Thread(tg1, runnable,"two");
t2.start( );
Thread t3 = new Thread(tg1, runnable,"three");
t3.start( );
System.out.println("Thread Group Name: "+tg1.getName( ));
tg1.list( );
}
}
Generic Programming
 The Java Generics programming is introduced in JDK 5 to deal with type-safe objects. Before
generics, we can store any type of objects in the collection, i.e., non-generic. Now generics force the
java programmer to store a specific type of objects.
 The Object is the superclass of all other classes and Object reference can refer to any type object.
These features lack type safety. Generics add that type safety feature.
 The term generics means parameterized types. Parameterized types are important because they
enable you to create classes, interfaces, and methods in which the type of data upon which they
operate is specified as a parameter. Using generics, it is possible to create a single class, for
example, that automatically works with different types of data. A class, interface, or method that
operates on a parameterized type is called generic, as in generic class or generic method.
Advantage of Java Generics
There are mainly 3 advantages of generics. They are as follows:
1) Type-safety: We can hold only a single type of objects in generics. It doesn’t allow to store other
objects.
2) Type casting is not required: There is no need to typecast the object.
3) Compile-Time Checking: It is checked at compile time so problem will not occur at runtime. The
good programming strategy says it is far better to handle the problem at compile time than runtime.
Generic class
A class that can refer to any type is known as a generic class. Here, we are using the T type parameter
to create the generic class of specific type.
Syntax 
To use generic collection
class class-name<type-param-list > 
Declaring a reference to a generic class
class-name<type-arg-list > var-name = new class-name<type-arg-list > (cons-arg-list);
public class Box<T>
{ } 
Box <Type> obj = new Box <Type>( ) // To create an instance of generic class
Example
public class Genclass <T>
{
T obj1; int a;
Genclass(T obj) string ch;
{
obj1 = obj;
}
public T getObject( )
{
return obj1;
}
public static void main(String[] args)
{
Genclass <Integer> iObj = new Genclass<Integer>(15);
System.out.println(iObj.getObject());
Genclass <String> sObj = new Genclass<String>("Welcome");
System.out.println(sObj.getObject());
}
}
run:
15
GeeksForGeeks
Generics Work Only with Objects (Reference Types)
When declaring an instance of a generic type, the type argument passed to the type parameter must
be a class type. You cannot use a primitive type, such as int or char.
Example
Gen<int> intOb = new Gen<int>(53); // Error, can't use primitive type
Multiple Type parameters in Generic classes
Declare more than one type parameter in a generic type. To specify two or more type parameters, simply use a comma-separated
list.
Example
public class Genclass <T, U>
{
T obj1;
U obj2;
Genclass(T objt, U obju)
{
obj1 = objt;
obj2 = obju;
} // constructor
public void getObject( )
{
System.out.println(obj1);
System.out.println(obj2);
}
public static void main(String[ ] args)
{
Genclass <String, Integer> obj = new Genclass<String, Integer>(“Welcome", 15);
obj.getObject( );
}
}
Generic Method
Like the generic class, we can create a generic method that can accept any type of arguments.
Based on the types of the arguments passed to the generic method, the compiler handles each method call
appropriately. Following are the rules to define Generic Methods −
All generic method declarations have a type parameter section delimited by angle brackets (< and >) that precedes the
method's return type ( < E > in the next example).
Each type parameter section contains one or more type parameters separated by commas. A type parameter, also
known as a type variable, is an identifier that specifies a generic type name.
The type parameters can be used to declare the return type and act as placeholders for the types of the arguments
passed to the generic method, which are known as actual type arguments.
A generic method's body is declared like that of any other method. Note that type parameters can represent only
reference types, not primitive types (like int, double and char).
Example
public class Genclass <T>
{
public static < E > void printArray(E[] elements)
{
for ( E element123 : elements)
{
System.out.println(element123 );
}
}
public static void main( String args[] )
{
Integer[ ] intArray = { 10, 20, 30, 40, 50 };
Character[ ] charArray = { 'J', 'A', 'V', 'A', 'T','P','O','I','N','T' };
Double[ ] doubleArray = { 1.1, 2.2, 3.3, 4.4 };
System.out.println( "Printing Integer Array" );
printArray( intArray );
System.out.println( "Printing Character Array" );
printArray( charArray );
System.out.println("Printing Double Array:");
printArray(doubleArray);
}
}
Generic Types Differ Based on Their Type Arguments: 
Consider the following Java code. 
Test <Integer> iObj = new Test<Integer>(15);
System.out.println(iObj.getObject());

Test <String> sObj = new Test<String>(“Welcome");


System.out.println(sObj.getObject());

iObj = sObj; //This results an error


Bounded Type
There may be times when you'll want to restrict the kinds of types that are allowed to be passed to a type parameter.
For example, a method that operates on numbers might only want to accept instances of Number or its subclasses.
This is what bounded type parameters are for.
Declaration
 List the type parameter’s name
 Along by the extends keyword
 And by its upper bound
Syntax
<T extends superClassName>
Example
class Sample <T extends Number>
{
T data12;
Sample(T data)
{
data12 = data;
}
public void display()
{
System.out.println("Data value is: "+data12);
}
}
public class Genclass
{
public static void main(String args[])
{
Sample<Integer> obj1 = new Sample<Integer>(20);
obj1.display();
Sample<Double> obj2 = new Sample<Double>(20.22d);
obj2.display();
Sample<Float> obj3 = new Sample<Float>(125.332f);
obj3.display();
}
}
run:
Data value is: 20
Data value is: 20.22
Data value is: 125.332
Restrictions and Limitations
 Cannot Instantiate Generic Types with Primitive Types
 Cannot Create Instances of Type Parameters
 Cannot Declare Static Fields Whose Types are Type Parameters
 Cannot Use Casts or instanceof With Parameterized Types
 Cannot Create Arrays of Parameterized Types
 Cannot Create, Catch, or Throw Objects of Parameterized Types
 Cannot Overload a Method Where the Formal Parameter Types of Each Overload Erase to the Same
Raw Type
Difference between multitasking and multithreading
Multitasking Multithreading
Multitasking let CPU to execute multiple tasks at the Multithreading let CPU to execute multiple threads of
same time. a process simultaneously.
In multitasking CPU switches between programs In multithreading CPU switches between the threads
frequently. frequently.
In multitasking system has to allocate separate In multithreading system has to allocate memory to a
memory and resources to each program that CPU is process, multiple threads of that process shares the
executing. same memory and resources allocated to the process.

In multitasking, CPU is provided in order to execute While in multithreading also, CPU is provided in
many tasks at a time. order to execute many threads from a process at a
time.

Multitasking is slow compared to multithreading. While multithreading is faster.

In multitasking, termination of process takes more While in multithreading, termination of thread takes
time. less time.

You might also like