Java Fundamentals and Mutlithreading
Java Fundamentals and Mutlithreading
https://www.youtube.com/watch?v=2TZMjmp6Vts
Java Design goal
High performance
● Java provides high performance with the help of features like
JVM, interpretation, and its simplicity.
Dynamic
● Java is said to be dynamic because the java byte code may be dynamically
updated on a running system and it has a dynamic memory allocation
and deallocation (objects and garbage collector).
Standalone applications
Encapsulation This wraps code and data into a single unit. implementation of
abstraction.
Inheritance Inheritance allows us to define a class that inherits all the methods and
properties from another class
ABSTRACTION : Process of identifying the essential details to be known and ignoring the
non-essential details from the perspective of the user of the system
ENCAPSULATION
How is a swipe machine
used for payment of bill in a
retail store?
Swipe machine in a retail store
– Used by billing staff to key the amount
– Used by admin to record payment
41
INHERITANCE What are the two
different types of
customers you can see
in the retail
Customers are of two kinds application?
– Regular
– Privileged All customers have Customer Id, Name,
Telephone Number and Address
The regular customer in addition is given
discounts Privileged
All customers have some generic features. The Regular
The privileged customer gets a membership Customers Customers
different kinds of customers have all generic
card based on which gifts are given
features in addition to some specific features
INHERITANCE : Is a mechanism which allows to define generalized characteristics and behavior and also create
specialized ones. The specialized ones automatically tend to inherit all the properties of the generic ones
42
TYPES OF INHERITANCE
Grand
Father Animal
Father Bird Mammal
Father Wild Domestic
Son
Son Lion
Bat
43
POLYMORPHISM
What do you
observe in this
• Payment of bill - Two modes retail store
scenario?
– Cash (Calculation includes VAT)
Total Amount = Purchase amount +
VAT
The activity of paying the bill is the same. But the formula for calculation of bill
differs as per the mode of payment
When we compile source files(in essence source code) using a compiler(in java it is
javac), the compiler generates a binary file and automatically saves it in our machine.
Single-line Comments
Single-line comments start with two forward slashes (//).
System.out.println("Hello World");
Syntax of a Class Declaring a Java Method
class <class_name>
The syntax to declare a method is:
{
field; returnType methodName()
{
method;
// method body
} }
Basic programming constructs
Class Fundamentals
What is a Class in Java?
• A class is a group of objects which have common properties. It is a template or blueprint from which objects
are created. It is a logical entity.
What is Object?
Characteristics of an Object:
• Behavior: It represents the behavior (functionality) of an object such as deposit, withdraw, etc.
• Identity: An object's identity is typically implemented via a unique ID. The ID's value is not visible to the
external user; however, it is used internally by the JVM to identify each object uniquely.
Object Definitions:
• An object is a real-world entity.
• An object is a runtime entity.
• The object is an entity which has state and behavior.
• The object is an instance of a class.
Syntax of a Class
Example:
class <class_name> class Person
{
{ String name;
field; int age;
{ // calling method
return sum; }
}
Sum is:
40
}
class Main
{
// create a method
public int square(int num)
{
// return statement
return num * num;
}
public static void main(String[] args)
{
int result;
// call the method
// store returned value to result
Main object1=new Main();
result = object1.square(10);
System.out.println("Squared value of 10 is: " + result);
}
}
class Main
{
// method with no parameter
public void display1()
{
System.out.println("Method without parameter");
}
// method with single parameter
public void display2(int a)
{
System.out.println("Method with a single parameter: " +
a);
}
public static void main(String[] args)
{
// create an object of Main
Main obj = new Main();
// calling method with no parameter
obj.display1();
// calling method with the single parameter
obj.display2(24);
}
//Java Program to illustrate how to define a class and fields
//Defining a Student class.
class Student
{
//defining fields
int id=10;//field or data member or instance variable
String name="ADHYA";
//creating main method inside the Student class
import java.io.*;
OUTPUT: Demo@214c265e
class Demo {
int x = 10; x = 10
int display() 0
{
System.out.println("x = " + x);
return 0;
}
}
class Main {
public static void main(String[] args)
{
Demo D1 = new Demo(); // point 1
System.out.println(D1); // point 2
System.out.println(D1.display()); // point 3
}
Java program by using 2 classes
// Java program to demonstrate reference
// variable in java
import java.io.*;
OUTPUT: Demo@214c265e
class Demo {
int x = 10; x = 10
int display() 0
{
System.out.println("x = " + x);
return 0;
}
}
class Main {
public static void main(String[] args)
{
Demo D1 = new Demo(); // point 1
System.out.println(D1); // point 2
System.out.println(D1.display()); // point 3
}
class Circle
{ By using two classes:
double radius;
An array of objects works similarly to an array of primitive types but instead of storing primitive values, it
stores references (addresses) to objects in memory.
Key Points:
1. Array Declaration: You can declare an array of objects of a particular class type.
2. Array Initialization: Just like arrays of primitive types, arrays of objects can be initialized with a specific
size or values.
3. Object Creation: Each element in the object array is a reference, and it can be assigned an object
(instance of a class).
4. Accessing Object Fields and Methods: You can access the fields and methods of objects in the array
using the object references.
class Book
{ public class Main
String title; {
String author; public static void main(String[] args)
{
public Book(String title, String author) // Inline initialization of an array of Book objects
{ Book[] books = {
this.title = title; new Book("1984", "George Orwell"),
this.author = author; new Book("To Kill a Mockingbird", "Harper Lee"),
new Book("The Great Gatsby", "F. Scott Fitzgerald")
}
};
● Since java does not support multiple inheritance in case of class, but by using
interface it can achieve multiple inheritance .
Rule
Rohit
JIIT
Default Interface Methods
● A default method lets you define a default implementation for an interface
method.
Built-in Packages
The Java API is a library of prewritten classes, that are free to use, included in the
Java Development Environment.
The library contains components for managing input, database programming, and much
much more. The complete list can be found at Oracles website:
https://docs.oracle.com/javase/8/docs/api/.
The library is divided into packages and classes. Meaning you can either import a single class
(along with its methods and attributes), or a whole package that contain all the classes that
belong to the specified package.
To use a class or a package from the library, you need to use the import keyword:
Syntax
If you find a class you want to use, for example, the Scanner class, which is used to get user input, write the following code:
Example
import java.util.Scanner;
User-defined Packages MyPackageClass.java
To create your own package, you need to
package mypack;
understand that Java uses a file system
directory to store them. Just like folders class MyPackageClass
on your computer:
{
Example
└── root public static void main(String[] args)
└── mypack
{
└── MyPackageClass.java
System.out.println("This is my package!");
To create a package, use the package keyword:
}
Prog 1
Note : MyClass.java must be saved inside the myPackage
directory since it is a part of the package.
Prog 2
/* File name : Animal.java */package animals;
/* File name : MammalInt.java */
package animals;
public class MammalInt implements Animal {
interface Animal {
public void eat(); public void eat() {
System.out.println("Mammal eats");
public void travel();
}
}
public void travel() {
System.out.println("Mammal travels");
}
To compile : $ javac -d . Animal.java
public int noOfLegs() { $ javac -d . MammalInt.java
return 0;
}
interface Animal {
public void eat();
public void travel();
package payroll;
public class Boss package payroll;
{
import payroll.Employee;
public void payEmployee(Employee e)
{
public class Boss
e.mailCheck(); {
} public void payEmployee(Employee e)
} {
e.mailCheck();
package payroll; }
Thread-Based Multitasking
As we discussed above Threads are provided with lightweight nature and share the same address
space, and the cost of communication between threads is also low.
Why Threads are used?
Threads are used as they had the advantage of being lightweight and can
provide communication between multiple threads at a Low Cost contributing
to effective multi-tasking within a shared memory environment.
Life Cycle of Thread
During its lifetime, a thread transitions through several states, they are:
1. New State
2. Active State
3. Waiting/Blocked State
5. Terminated State
Stages of thread:
LIFE CYCLE OF A THREAD
New − A new thread begins its life cycle in the new state. It remains in this state until the program
Runnable − After a newly born thread is started, the thread becomes runnable. A thread in this state
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
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
Terminated (Dead) − A runnable thread enters the terminated state when it completes its task or
otherwise terminates.
Creation of Threads using Java Programming Language
It can be created by extending the Thread class and overriding its run() method:
}
Another way to create a thread is to implement the Runnable interface:
}
class Multi extends Thread
System.out.println("thread is running...");
t1.start();
}
Running Threads
If the class extends the Thread class, the thread can be run by creating an instance of the class and call its start()
method:
public class Main extends Thread
{
public static void main(String[] args)
{
Main thread = new Main();
thread.start();
System.out.println("This code is outside of the thread");
}
public void run()
{
System.out.println("This code is running in a thread");
}
If the class implements the Runnable interface, the thread can be run by passing an instance of the class
to a Thread object's constructor and then calling the thread's start() method:
}
If you are not extending the Thread class, your class object would not be treated as a thread object.
So you need to explicitly create the Thread class object. We are passing the object of your class
that implements Runnable so that your class run() method may execute.
obj.start();
obj.start();
for(int i=0;i<5;i++)
{
System.out.println("Hello i am main thread");
}
}
}
package ecom;
public class mainthread {
public static void main(String[] args) {
// TODO Auto-generated method stub
Multi obj=new Multi();
System.out.println(obj.getState());
//obj.start();
//obj.start();
for(int i=0;i<5;i++)
{
System.out.println("Hello i am main thread");
}
}
}
NEW
Hello i am main thread
Hello i am main thread
Hello i am main thread
Hello i am main thread
Hello i am main thread
package ecom; package ecom;
public class Multi extends Thread{ public class mainthread
public void run() {
public static void main(String[] args)
{
{
for(int i=0;i<5;i++) // TODO Auto-generated method stub
{ Multi obj=new Multi();
System.out.println("Hello i am main System.out.println(obj.getState());
obj.start();
thread"); System.out.println(obj.getState());
} //obj.start();
} for(int i=0;i<5;i++)
{
System.out.println("Hello thread");
NEW }
RUNNABLE }
Hello i am main thread
Hello i am main thread }
} Hello i am main thread
Hello i am main thread
Hello i am main thread
Hello thread
Hello thread
Hello thread
Hello thread
Hello thread
start(): it implicitly call the run() method.
sleep(milliseconds):it suspends the thread for given milliseconds & time. It is static
Thread.sleep(1000):it uses try catch method to handle exception. No object is
created to call static method .By using thread class it is called.
join():No object is created to call static method .By using thread class it is called.It
is static. it uses try catch method to handle exception.
It Waits until the another thread to complete its process.For ex: if one thread is
given as join() then the another thread has to wait until it completes its process.
getId(): gives the ID of the thread. obj.getId();
getName(): gives the thread name.obj.getName();
setName(String): Thread name will be replaced with given string.
obj.setName(“arudhra”);
getPriority(): priority ranges from 1 to 10.
MIN_PRIORITY=1
NORM_PRIORITY=5
MAX_PRIORITY=10
Normally the priority of thread will be 5.
setPriority(int): setPriority(10);
isAlive(): status of the thread
True: thread is still running
False: thread completes its execution
package threads;
package threads;
public class threadmain
public class threadsprgm extends Thread {
{ public static void main(String[] args)
public void run() {
{ // TODO Auto-generated method stub
for(int i=0;i<=4;i++) threadsprgm th=new threadsprgm();
{ th.start();
System.out.println(i); System.out.println("ID of the thread"+th.getId());
} System.out.println("Name of the thread"+
} th.getName());
} th.setName("Arudhra");
System.out.println("after changing the name"+ " "+
th.getName());
}
}
package threads;
package threads;
public class threadmain
public class threadsprgm extends Thread {
{ public static void main(String[] args)
public void run()
{
{
for(int i=0;i<=4;i++) // TODO Auto-generated method stub
{ threadsprgm th=new threadsprgm();
try { th.start();
Thread.sleep(1000); System.out.println("ID of the thread"+th.getId());
}
System.out.println("Name of the thread"+ th.getName());
catch(Exception e)
{ th.setName("Arudhra");
System.out.println("after changing the name"+ " "+
} th.getName());
System.out.println(i);
}
} }
} }
package threads; package threads;
public class threadsprgm extends Thread public class threadmain
{ {
public void run() public static void main(String[] args)
{ {
Thread t=currentThread();//object // TODO Auto-generated method stub
reference whatever thread starts from that is threadsprgm th=new threadsprgm();
stored in it th.start();
for(int i=0;i<=4;i++) System.out.println("ID of the thread"+th.getId());
{ System.out.println("Name of the thread"+ th.getName());
try { th.setName("Arudhra");
t.sleep(1000); System.out.println("after changing the name"+ " "+ th.getName())
}
catch(Exception e) }
{ }
OUTPUT:
} ID of the thread10
System.out.println(i); Name of the threadThread-0
} after changing the name Arudhra
}
0
}
1
2
3
4
package threads;
public class threadsprgm extends Thread package threads;
{ public class threadmain
public void run() {
{ public static void main(String[] args)
Thread t=currentThread();//object reference whatever {
thread starts from that is stored in it // TODO Auto-generated method stub
for(int i=0;i<=4;i++) threadsprgm th=new threadsprgm();
{ th.start();
try { System.out.println("ID of the thread"+th.getId());
System.out.println("Name of the thread"+ th.getName());
t.sleep(1000); th.setName("Arudhra");
} System.out.println("after changing the name"+ " "+ th.getNa
catch(Exception e)
System.out.println("Priority of the thread"+ th.getPriority()
{
th.setPriority(6);
System.out.println("Priority of the thread"+ th.getPriority()
}
System.out.println(i);
}
}
} }
} ID of the thread14
Name of the threadThread-0
after changing the name Arudhra
Priority of the thread5
Priority of the thread6
0
1
2
3
4
Commonly used methods of Thread class:
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 void join(long miliseconds): waits for a thread to die for the specified miliseconds.
public void setDaemon(boolean b): marks the thread as daemon or user thread.
public static boolean interrupted(): tests if the current thread has been interrupted.
Using the Thread Class: Thread(String Name)
public class MyThread1
{ Output:
// creating an object of the Thread class using the constructor Thread(String name)
t.start();
System.out.println(str);
} }
Using the Thread Class: Thread(Runnable r, String name)
public class MyThread2 implements Runnable
{
public void run()
{ Output:
System.out.println("Now the thread is running ..."); My new thread
} Now the thread is running ...
// main method
public static void main(String argvs[])
{
}
}
class mythread extends Thread
{
public void run() Output:
{
false
for(int i=0;i<4;i++) child thread
{ child thread
System.out.println("child thread"); child thread
} child thread
} true
}
class demothread
{
public static void main(String ar[])
{
mythread myobj=new mythread();
System.out.println(myobj.isAlive());
myobj.start();
System.out.println(myobj.isAlive());
}
}
What is a Thread Scheduler?
The Thread Scheduler in Java is part of the JVM (Java Virtual Machine) that decides
which thread to run next when there are multiple threads ready to run (in the
Runnable state).
Java does not guarantee the order in which threads will execute — the Thread
Scheduler makes that decision based on:
System.out.println(Thread.currentThread().get
t1.setName("Thread-1");
Name() + " is running with priority " + t2.setName("Thread-2");
Thread.currentThread().getPriority()); t3.setName("Thread-3");
}
} t1.setPriority(Thread.MIN_PRIORITY); // Priority 1
t2.setPriority(Thread.NORM_PRIORITY); // Priority 5 (default)
t3.setPriority(Thread.MAX_PRIORITY); // Priority 10
Output: Thread-3 is running with priority 10
Thread-2 is running with priority 5
Thread-1 is running with priority 1 t1.start();
This output may vary each time you run the t2.start();
program because the thread scheduler t3.start();
behavior depends on the JVM and OS.
} }
What is a Thread Pool in Java?
A Thread Pool is a group of worker threads that are ready to perform tasks.
Instead of creating a new thread every time (which is costly), Java uses a pool of
pre-created threads. When a task comes, it reuses one of the threads from the pool.
★ Limits the number of threads → prevents the system from being overloaded.
★ The pool will run only 3 tasks in parallel at a time. As threads become available, they pick up
the remaining tasks.
Here, the run() method of the MyTask class is called indirectly by the thread
pool when you submit the task using:
executor.execute(task);
public class ThreadGroupExample
{
@Override
public void run() {
System.out.println("Sending email to: " + email + " | Thread: " + Thread.currentThread().getName());
try {
Thread.sleep(2000); // Simulate delay in sending email
} catch (InterruptedException e) {
System.out.println("Email sending interrupted for: " + email);
}
System.out.println("Email sent to: " + email);
}
}
public class EmailSender {
public static void main(String[] args) {
// List of email addresses
String[] emailList = {
"[email protected]", "[email protected]", "[email protected]",
"[email protected]", "[email protected]", "[email protected]",
"[email protected]", "[email protected]", "[email protected]",
"[email protected]"
};
Defines a lambda expression (a short form for creating a class that implements Runnable).
Prints a message showing the current thread's name and that it's running.
try
{
Thread.sleep(1000); // Simulate work
The thread sleeps for 1 second (1000 milliseconds) to simulate some task or delay.
}
catch (InterruptedException e)
{
System.out.println(Thread.currentThread().getName() + " was interrupted");
}
If the thread is interrupted during sleep, this block will catch and handle the exception.
};
Each thread is passed: the group (group), the task (task), and a thread name ("Thread-1", etc.).
t1.start();
t2.start();
t3.start();
Starts all three threads — each one begins executing the code inside the Runnable (i.e., prints message and sleep
for 1 second).
group.list();
Prints detailed information about the group and all its threads, including names and priorities.
What is a Thread Group?
A Thread Group in Java is used to group multiple threads into a single unit for easier
management. You can:
1. 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:
1. Synchronized method.
2. Synchronized block.
3. Static synchronization.
100
10
200
15
300
20
400
25
500
class Table {
class MyThread2 extends Thread {
// Synchronized method to print the table Table t;
synchronized void printTable(int n) { // Constructor to initialize Table object
for(int i = 1; i <= 5; i++) { MyThread2(Table t) {
// Print the multiplication result this.t = t;
System.out.println(n * i); }
try { // Run method to execute thread
// Pause execution for 400 milliseconds public void run() {
Thread.sleep(400); // Call synchronized method printTable with argument 100
} catch(Exception e) {
t.printTable(100);
// Handle any exceptions
}
System.out.println(e);
}
}
} public class Main {
} public static void main(String args[]) {
} // Create a Table object
class MyThread1 extends Thread { Table obj = new Table();
Table t; // Create MyThread1 and MyThread2 objects with the
// Constructor to initialize Table object same Table object
MyThread1(Table t) { MyThread1 t1 = new MyThread1(obj);
this.t = t; MyThread2 t2 = new MyThread2(obj);
}
// Start both threads
// Run method to execute thread
t1.start();
public void run() {
// Call synchronized method printTable with argument 5
t2.start();
t.printTable(5); }
}
Output:
5
10
15
20
25
100
200
300
400
500
public class Main {
Synchronized Method by Using Anonymous Class
public static void main(String args[]) {
In this program, we have created the two threads by using the // Create a Table object
anonymous class, so less coding is required. final Table obj = new Table(); // Only one object
// Create thread t1 using anonymous class
Example Thread t1 = new Thread() {
// Program of synchronized method by using anonymous public void run() {
class // Call synchronized method printTable wit
class Table { argument 5
// Synchronized method to print the table obj.printTable(5);
synchronized void printTable(int n) { }
for(int i = 1; i <= 5; i++) { };
// Print the multiplication result // Create thread t2 using anonymous class
System.out.println(n * i); Thread t2 = new Thread() {
try { public void run() {
// Pause execution for 400 milliseconds // Call synchronized method printTable wit
Thread.sleep(400); argument 100
} catch(Exception e) { obj.printTable(100);
// Handle any exceptions }
System.out.println(e); };
} // Start both threads
} t1.start();
} t2.start();
} }
Synchronized Block
Java 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.
Points to Remember
○ Synchronized block is used to lock an object for any shared resource.
○ Scope of synchronized block is smaller than the method.
○ A Java synchronized block doesn't allow more than one JVM, to provide access control to a shared resource.
○ The system performance may degrade because of the slower working of synchronized keyword.
○ Java synchronized block is more efficient than Java synchronized method.
//Creating Thread Class to call method
//Creating a class which contains synchronized block within class MyThread1 extends Thread
method {
class Table Table t;
{ MyThread1(Table t){
void printTable(int n){ this.t=t;
synchronized(this){//synchronized block }
for(int i=1;i<=5;i++){ public void run()
System.out.println(n*i); {
try{
Thread.sleep(400); t.printTable(5);
}catch(Exception e){System.out.println(e);} }
}
} }
}//end of the method class MyThread2 extends Thread
} {
//Creating Main class to start threads Table t;
public class Main{ MyThread2(Table t)
public static void main(String args[]){ {
Table obj = new Table();//only one object this.t=t;
MyThread1 t1=new MyThread1(obj); }
MyThread2 t2=new MyThread2(obj); public void run(){
t1.start(); t.printTable(100);
t2.start(); }
} } }
Output:
5
10
15
20
25
100
200
300
400
500
Synchronized Static method
If a thread is in the static synchronized region, all other threads trying to access this
region will be blocked.
Since static methods belong to the class therefore, static synchronization applies class
level lock.
class Counter {
private static int count = 0;
Inter thread communication is a mechanism in which one thread goes to wait state until
the another thread sends a notification.
wait(): A thread goes into sleep or wait state until some other thread sends
notification.
public void notifyAll(): Wakes up all the threads that called wait( ) on the
same object.
class ThreadB extends Thread {
int totalBalance = 0;
}
Main thread starts
After the loop and calculation, it calls notify() inside the synchronized
block.
After being notified, the main thread continues and prints the result.