Core JAVA
Java Runtime Environment (JRE)
Java Virtual Machine (JVM)
Java overview
Java basics
Java Objects and classes
Java Constructors
Java basic datatypes
Java variable types
Java modifiers/Access Modifiers In Java
Java Basic Operators
Java Loops and Controls
Java conditions
Java numbers and characters
Java strings
Java arrays
Java date time
Java methods
Java file and IO operations
Java exceptions
Inner class
Java OOPs Concepts
Java Inheritance
Java Polymorphism
Java Abstraction
Java Encapsulation
Java Interface
Cohesion and Coupling
Association, Aggregation and Composition
Java Collections
Java ArrayList
Java LinkedList
Set and HashSet
LinkedHashSet and TreeSet
Queue and PriorityQueue
Deque and PriorityQueue
Java Map Interface
Java HashMap
Internal Working Of Java HashMap
Java Mutithread
Methods of Thread In Java
Join , run & Start Method in Threads
Difference b/w start & run Methods in Threads
Java Concurrency Package & its Features
CountDownLatch, CyclicBarrier, Semaphore and Mutex in Thread
Java Multithreading
Ability to execute multiple tasks at the same time in a CPU is called multithreading. Java provides a lot of classes and methods to achieve multithreading in java. A thread is a small task in a multithreaded application which can run along with other threads in parallel(almost).
- A multithreaded code creates multiple parallel tasks which run on the CPU core at almost the same time.
- A process is different from multi-threading, multithreading can be part of a process, for example multithreading in java runs under java process.
- Multithreading enables you to run multiple small tasks and complete them in a concurrent and faster manner.
- Multithreading improves efficiency and performance of application but also creates locking and other issues related to concurrency, which should be handled carefully.
Life Cycle Of Thread
There are total 5 states of a thread in java:
1. New – It is the state when we create a thread with a new key word.
2. Runnable – When we call start() method of thread, the thread goes to Runnable state which means ready to execute. Later it may get picked up, based on machine architecture and OS and moved to running state.
3. Running – In this state thread starts executing code written in run() method.
4. Waiting(sleep or wait) – When a thread is called to wait for a certain specific time is called waiting.
5. Terminated(Dead )– When thread completes the task goes to dead/terminated state.
Diagram showing states of Thread:
Java Thread methods
S.N. |
Modifier and Return Type |
Method |
Description |
1) |
void |
start() |
Starts a thread (ensures does not run in same thread) |
2) |
void |
run() |
Runs the code of thread |
3) |
static void |
sleep() |
Makes the current thread sleep for a given time. |
4) |
static Thread |
currentThread() |
Returns the current thread. |
5) |
void |
join() |
It joins two threads and 2nd waits for 1st to complete. |
6) |
int |
getPriority() |
Returns priority. |
7) |
void |
setPriority() |
Sets priority of thread. |
8) |
String |
getName() |
Returns the name of the thread. |
9) |
void |
setName() |
Sets the name of thread. |
10) |
long |
getId() |
Returns id of thread. |
11) |
boolean |
isAlive() |
Checks if the thread is alive. |
12) |
static void |
yield() |
Causes the current running thread to pause and allows another to run. |
13) |
void |
suspend() |
Suspends current thread. |
14) |
void |
resume() |
Resumes thread from suspension. |
15) |
void |
stop() |
Stop the thread. |
16) |
void |
destroy() |
It destroys thread and group of it. |
17) |
boolean |
isDaemon() |
Checks if thread is daemon. |
18) |
void |
setDaemon() |
Sets a thread to be daemon. |
19) |
void |
interrupt() |
It interrupts the thread. |
20) |
boolean |
isinterrupted() |
Checks if the thread is interrupted or not. |
21) |
static boolean |
interrupted() |
It tests whether the current thread has been interrupted. |
22) |
static int |
activeCount() |
Returns active threads count in the current thread group. |
23) |
void |
checkAccess() |
Checks if the current thread has access to modify. |
24) |
static boolean |
holdLock() |
Returns true if the current thread holds the monitor on object. |
25) |
static void |
dumpStack() |
Prints stack trace of thread. |
26) |
StackTraceElement[] |
getStackTrace() |
Returns stack trace of thread. |
27) |
static int |
enumerate() |
|
28) |
Thread.State |
getState() |
Return state. |
29) |
ThreadGroup |
getThreadGroup() |
Returns thread group. |
30) |
String |
toString() |
Returns string of thread name, priority, group etc. |
31) |
void |
notify() |
It signals a specific thread which is waiting for an object.. |
32) |
void |
notifyAll() |
It signals all threads in the waiting state of an object. |
33) |
void |
setContextClassLoader() |
Loads context class |
34) |
ClassLoader |
getContextClassLoader() |
Loads context class |
35) |
static Thread.UncaughtExceptionHandler |
getDefaultUncaughtExceptionHandler() |
Returns default exception handler. |
36) |
static void |
setDefaultUncaughtExceptionHandler() |
Sets default exception handler. |
Thread Creation In Java
There are two ways to create a thread in Java.
1. By extending Thread class
2. By implementing Runnable interface and overriding run() method.
There are some differences in the above two approaches.
1. By using extend approach your class can’t extend any other class as it is already used while in case of Runnable interface your class may still extend some class.
2. Runnable approach creates an object and we pass that object to thread while in case of extending it is not so.
Example Of Java Thread Creation By Extending Thread Class
See below example of producer and consumer thread which are extending Thread class. Study it to understand.
package threads;
import java.util.Date;
import java.util.concurrent.BlockingDeque;
import java.util.concurrent.LinkedBlockingDeque;public class MyExtendThread extends Thread {
public static void main(String[] args) {
BlockingDeque<String> bqueue = new LinkedBlockingDeque<String>(5);//Producer thread start
Producer producer = new Producer(bqueue);
producer.start();Producer producer2 = new Producer(bqueue);
producer2.start();//Created Consumer thread
Consumer consumerThread = new Consumer(bqueue);
consumerThread.start();
System.out.println("Main thread is dead, this does not mean other threads are dead, they still live");
}
}class Producer extends Thread {
BlockingDeque<String> bqueue = new LinkedBlockingDeque<String>();
public Producer(BlockingDeque<String> bqueue) {
this.bqueue = bqueue;
}public void run() {
while(true){
String date = new Date().toString();
bqueue.add(date);
System.out.println("Producer - I have added: "+date+" in blocking queue, capacity now:"+bqueue.size()+" name"+Thread.currentThread().getName());
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
class Consumer extends Thread {
BlockingDeque<String> bqueue = new LinkedBlockingDeque<String>();
public Consumer(BlockingDeque<String> bqueue) {
this.bqueue = bqueue;
}public void run() {
while(true){
String date ="";
try {
date = bqueue.take();
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("Consumer - I have removed: "+date+" something from blocking queue, capacity now:"+bqueue.size()+" name"+Thread.currentThread().getName());
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
Output:
Main thread is dead, this does not mean other threads are dead, they still live
Producer - I have added: Wed Sep 15 18:54:35 IST 2021 in blocking queue, capacity now:0 nameThread-1
Consumer - I have removed: Wed Sep 15 18:54:35 IST 2021 something from blocking queue, capacity now:1 nameThread-2
Producer - I have added: Wed Sep 15 18:54:35 IST 2021 in blocking queue, capacity now:1 nameThread-0
Consumer - I have removed: Wed Sep 15 18:54:35 IST 2021 something from blocking queue, capacity now:0 nameThread-2
Producer - I have added: Wed Sep 15 18:54:36 IST 2021 in blocking queue, capacity now:2 nameThread-0
Producer - I have added: Wed Sep 15 18:54:36 IST 2021 in blocking queue, capacity now:1 nameThread-1
Consumer - I have removed: Wed Sep 15 18:54:36 IST 2021 something from blocking queue, capacity now:1 nameThread-2
Producer - I have added: Wed Sep 15 18:54:37 IST 2021 in blocking queue, capacity now:3 nameThread-1
Producer - I have added: Wed Sep 15 18:54:37 IST 2021 in blocking queue, capacity now:3 nameThread-0
Example of Java Thread Creation By Implementing Runnable Interface
package threads;
import java.util.Date;
import java.util.concurrent.BlockingDeque;
import java.util.concurrent.LinkedBlockingDeque;class MyRunnableThread extends Thread {
public static void main(String[] args) {BlockingDeque<String> bqueue = new LinkedBlockingDeque<String>(5);
//Producer thread start
ProducerRunnable producer = new ProducerRunnable(bqueue);
new Thread(producer).start();Producer producer2 = new Producer(bqueue);
producer2.start();//Created Consumer thread
ConsumerRunnable consumerThread = new ConsumerRunnable(bqueue);
new Thread(consumerThread).start();
System.out.println("Main thread is dead, this does not mean other threads are dead, they will still live");
}
}
class ProducerRunnable implements Runnable {
BlockingDeque<String> bqueue;public ProducerRunnable(BlockingDeque<String> bqueue) {
this.bqueue = bqueue;
}public void run() {
while(true){
String date = new Date().toString();
bqueue.add(date);
System.out.println("Producer - I have added: "+date+" in blocking queue, capacity now:"+bqueue.size()+" name"+Thread.currentThread().getName());
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}class ConsumerRunnable implements Runnable {
BlockingDeque<String> bqueue;
public ConsumerRunnable(BlockingDeque<String> bqueue) {
this.bqueue = bqueue;
}public void run() {
while(true){
String date ="";
try {
date = bqueue.take();
} catch (InterruptedException e) {
e.printStackTrace();
}System.out.println("Consumer - I have removed: "+date+" something from blocking queue, capacity now:"+bqueue.size()+" name"+Thread.currentThread().getName());
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
Output
Main thread is dead, this does not mean other threads are dead, they will still live
Producer - I have added: Thu Sep 16 10:18:27 IST 2021 in blocking queue, capacity now:0 nameThread-0
Consumer - I have removed: Thu Sep 16 10:18:27 IST 2021 something from blocking queue, capacity now:1 nameThread-2
Producer - I have added: Thu Sep 16 10:18:27 IST 2021 in blocking queue, capacity now:1 nameThread-1
Consumer - I have removed: Thu Sep 16 10:18:27 IST 2021 something from blocking queue, capacity now:0 nameThread-2
Producer - I have added: Thu Sep 16 10:18:28 IST 2021 in blocking queue, capacity now:2 nameThread-0
Producer - I have added: Thu Sep 16 10:18:28 IST 2021 in blocking queue, capacity now:1 nameThread-1
Consumer - I have removed: Thu Sep 16 10:18:28 IST 2021 something from blocking queue, capacity now:1 nameThread-2
Producer - I have added: Thu Sep 16 10:18:29 IST 2021 in blocking queue, capacity now:3 nameThread-0
Producer - I have added: Thu Sep 16 10:18:29 IST 2021 in blocking queue, capacity now:2 nameThread-1
Consumer - I have removed: Thu Sep 16 10:18:28 IST 2021 something from blocking queue, capacity now:2 nameThread
Example of Thread Creation Using Functional Interface and Lambda Expression
package threads;
public class LambdaExpressionThreads {
public static void main(String[] args) {//Using functional interface concept
new Thread(new Runnable() {
@Override
public void run() {
System.out.println("I am a thread, created without lambda with functional interface.");
}
}).start();//Lamda expression to create thread, same as above but with lamda
new Thread(() -> {
System.out.println("I am a thread, created with lambda expression.");
}).start();
}
}
Output
I am a thread, created without lambda with a functional interface.
I am a thread, created with lambda expressions.