Unit 4 Cs3452 Java 1
Unit 4 Cs3452 Java 1
Thread :
A thread is a single sequential( separate ) flow of control within program. Sometimes, it is called
an execution context or light weight process.
Multithreading:
Multithreading is a conceptual programming concept where a program (process) is divided into
two or more subprograms (process), which can be implemented at the same time in parallel. A
multithreaded program contains two or more parts that can run concurrently. Each part of such a
program is called a thread, and each thread defines a separate path of execution.
Multitasking:
Executing several tasks simultaneously is called multi-tasking.
There are 2 types of multi-tasking
1. Process-based multitasking
2. Thread-based multi-tasking
1. Process-based multi-tasking
Executing various jobs together where each job is a separate independent operation, is
called process-based multi-tasking.
2. Thread-based multi-tasking
Executing several tasks simultaneously where each task is a separate independent part of
the same program is called Thread-based multitasking and each independent part is called
Thread. It is best suitable for the programmatic level. The main goal of multi-tasking is to make
or do a better performance of the system by reducing response time
Multithreading vs Multitasking
Multithreading is to execute multiple Multitasking is to run multiple processes on
threads in a process concurrently. a computer concurrently.
Execution
In Multithreading, the CPU switches In Multitasking, the CPU switches between
between multiple threads in the same multiple processes to complete the
process. execution.
Resource Sharing
In Multithreading, resources are shared In Multitasking, resources are shared
among multiple threads in a process. among multiple processes.
Complexity
Multithreading is light-weight and easy to Multitasking is heavy-weight and harder to
create. create.
Example:
public class ThreadSample implements Runnable
{
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 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.
Example :
public class MyThread1 extends Thread {
MyThread1(String s)
{
super(s);
start();
}
public void run()
{
for(int i=0;i<5;i++)
{
Thread cur=Thread.currentThread();
cur.setPriority(Thread.MAX_PRIORITY);
int p=cur.getPriority();
System.out.println("Thread Name"+Thread.currentThread().getName());
System.out.println("Thread Priority"+cur);
}
}
}
SYNCHRONIZING THREADS
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
General Syntax :
synchronized(object)
{
//statement to be synchronized
}
Thread Synchronization
There are two types of thread synchronization mutual exclusive and inter-thread communication.
1.Mutual Exclusive
Synchronized method.
Synchronized block.
static synchronization.
2.Cooperation (Inter-thread communication in java)
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.
Example of synchronized method
package Thread;
public class SynThread
{
public static void main(String args[])
{
share s = new share();
MyThread m1 = new MyThread(s, "Thread1");
MyThread m2 = new MyThread(s, "Thread2");
MyThread m3 = new MyThread(s, "Thread3");
}
}
class MyThread extends Thread
{
share s;
MyThread(share s, String str)
{
super(str);
this.s = s;
start();
}
public void run()
{
s.doword(Thread.currentThread().getName());
}
}
class share
{
public synchronized void doword(String str)
{
for (int i = 0; i < 5; i++)
{
System.out.println("Started:" + str);
try
{
Thread.sleep(1000);
}
catch (Exception e)
{
}}}}
SYNCHRONIZED BLOCK
Synchronized block can be used to perform synchronization on any specific resource of
the method.
Suppose you have 50 lines of code in your method, but you want to synchronize only 5
lines, you can use synchronized block.
If you put all the codes of the method in the synchronized block, it will work same as the
synchronized method.
Example of synchronized block
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 Table{
synchronized static void printTable(int n){
for(int i=1;i<=10;i++){
System.out.println(n*i);
try{
Thread.sleep(400);
}catch(Exception e){}
}
}
}
class MyThread1 extends Thread{
public void run(){
Table.printTable(1);
}
}
class MyThread2 extends Thread{
public void run(){
Table.printTable(10);
}
}
class MyThread3 extends Thread{
public void run(){
Table.printTable(100);
}
}
class MyThread4 extends Thread{
public void run(){
Table.printTable(1000);
}
}
public class TestSynchronization4{
public static void main(String t[]){
MyThread1 t1=new MyThread1();
MyThread2 t2=new MyThread2();
MyThread3 t3=new MyThread3();
MyThread4 t4=new MyThread4();
t1.start();
t2.start();
t3.start();
t4.start();
}
}
INTER-THREAD COMMUNICATION
Inter-thread communication or Co-operation is all about allowing synchronized threads to
communicate with each other.
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()
wait()
tells calling thread to give up monitor and go to sleep until some other thread enters the
same monitor and call notify.
notify()
wakes up a thread that called wait() on same object.
notifyAll()
wakes up all the thread that called wait() on same object.
wait() sleep()
wait() method releases the lock sleep() method doesn't release the lock.
Now all 3 threads belong to one group. Here, tg1 is the thread group name, MyRunnable
is the class that implements Runnable interface and "one", "two" and "three" are the thread
names.
ThreadGroup Example
public class ThreadGroupDemo implements Runnable{
public void run() {
System.out.println(Thread.currentThread().getName());
}
public static void main(String[] args) {
ThreadGroupDemo runnable = new ThreadGroupDemo();
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();
}
}
Output:
one
two
three
Thread Group Name: Parent ThreadGroup
java.lang.ThreadGroup[name=Parent ThreadGroup,maxpri=10]
Thread[one,5,Parent ThreadGroup]
Thread[two,5,Parent ThreadGroup]
Thread[three,5,Parent ThreadGroup]
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
How to Avoid Deadlock in Java?
Deadlocks cannot be completely resolved. But we can avoid them by following basic rules
mentioned below:
1. Avoid Nested Locks: We must avoid giving locks to multiple threads, this is the main
reason for a deadlock condition. It normally happens when you give locks to multiple
threads.
2. Avoid Unnecessary Locks: The locks should be given to the important threads. Giving
locks to the unnecessary threads that cause the deadlock condition.
3. Using Thread Join: A deadlock usually happens when one thread is waiting for the other
to finish. In this case, we can use join with a maximum time that a thread will take.
Introduction to Generics:
Generics means parameterized types. The idea is to allow type (Integer, String, … etc., and
user-defined types) to be a parameter to methods, classes, and interfaces. Using Generics, it is
possible to create classes that work with different data types. An entity such as class, interface, or
method that operates on a parameterized type is a generic entity.
The Object is the superclass of all other classes, and Object reference can refer to any
object. These features lack type safety. Generics add that type of safety feature. We will discuss
that type of safety feature in later examples.
Generics in Java are similar to templates in C++. For example, classes like HashSet,
ArrayList, HashMap, etc., use generics very well. There are some fundamental differences
between the two approaches to generic types.
// constructor
Test(T obj1, U obj2)
{
this.obj1 = obj1;
this.obj2 = obj2;
}
obj.print();
}
}
Output:
GfG
15
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.
// Java program to show working of user defined
// Generic functions
class Test {
// A Generic method example
static <T> void genericDisplay(T element)
{
System.out.println(element.getClass().getName()
+ " = " + element);
}
// Driver method
public static void main(String[] args)
{
// Calling generic method with Integer argument
genericDisplay(11);
Output:
java.lang.Integer = 11
java.lang.String = WELCOME JAVA
java.lang.Double = 1.0
import java.util.*;
class Test
{
public static void main(String[] args)
{
// Creatinga an ArrayList without any type specified
ArrayList al = new ArrayList();
al.add("Welcome");
al.add("Java");
al.add(10); // Compiler allows this
String s1 = (String)al.get(0);
String s2 = (String)al.get(1);
class Test
{
public static void main(String[] args)
{
// Creating a an ArrayList with String specified
ArrayList <String> al = new ArrayList<String> ();
al.add("Welcome");
al.add("java");
String s1 = (String)al.get(0);
String s2 = (String)al.get(1);
String s3 = (String)al.get(2);
}
}
Output:
15: error: no suitable method found for add(int)
al.add(10);
^
Implementing Generic Algorithms: By using generics, we can implement algorithms that work
on different types of objects, and at the same, they are type-safe too.
Generics are basically the errors appearing are compile-time than at run-time. there are certain
advantages of generics over non-generic are as follows:
1. Code Reuse: With help of Generics, one needs to write a method/class/interface only
once and use it for any type whereas, in non-generics, the code needs to be written again
and again whenever needed.
2. Type Safety: Generics make errors to appear compile time than at run time (It’s always
better to know problems in your code at compile time rather than making your code fail
at run time).
Example: To create an ArrayList that store name of students and if by mistake programmer adds
an integer object instead of string, the compiler allows it. But, when this data is retrieved from
ArrayList, it causes problems at runtime for Non-generic ArrayList
// Java program to Demonstrate that Not Using Generics
// Can cause Run Time Exceptions
// Main class
class GFG {
String s1 = (String)al.get(0);
String s2 = (String)al.get(1);
// Main class
class GFG {
String s1 = al.get(0);
String s2 = al.get(1);
String s3 = al.get(2);
}
}
Output:
prog.java:24: error: incompatible types: int cannot be converted to String
al.add(10);
^
Note: Some messages have been simplified; recompile with -Xdiags:verbose to get full output
1 error
Now moving forward, Individual Type Casting is not needed.
If Generics is not needed, then, in the above example every time the data is to be retrieved from
ArrayList, it needs to be typecasted. Typecasting at every retrieval operation is a big headache.
This can be avoided if somehow it is already known that the list only holds string data.
// A Simple Java program to demonstrate that
// type casting is not needed in Generic
import java.util.*;
class Test {
public static void main(String[] args)
{
// Creating an ArrayList
// Declaring object of type String
ArrayList<String> al = new ArrayList<String>();
Output:
[Sachin, Rahul]
Differentate:
Base Non-generic Collection Generic Collection
Can hold any type of data. Can hold only the defined type of data.
Type-safety Hence not type-safe. Hence type safe.