Thread is a lightweight sub-process with a smallest unit of processing. Thread execution path is separate. Threads are independent. If any error or exception occured in one single thread it will not effect on other threads. It uses a shared memory.
To better understand this question, let’s first take a look at what is a Program. A Program is an executable file containing a set of instructions and passively stored on disk. One program can have multiple processes. For example, the Chrome browser creates a different process for every single tab.
A Process means a program is in execution. When a program is loaded into the memory and becomes active, the program becomes a process. The process requires some essential resources such as registers, program counter, and stack.
A Thread is the smallest unit of execution within a process.
The following process explains the relationship between program, process, and thread.
Main differences between process and thread:
The process of executing a multiple task simultaneously is nothing but multitasking. It can be achived two different ways.
Different stages in thread life cycle.
Thread can be created two ways:
Thread class provide constructors and methods to create and perform operations on a thread.Thread class extends Object class and implements Runnable interface.
Constructor | Description |
---|---|
Thread() | Can create a Thread object using default constructor. |
Thread(String name) | Can create a Thread object by passing the thread name in constructor. |
Thread(Runnable r) | Can create a Thread object by passing runnable interface in constructor. |
Thread(Runnable r,String name) | Can create a Thread object by passing thread name and runnable in constructor. |
Method name | Description |
---|---|
public void run(): | is used to perform action for a thread. |
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(): | waits for a thread to die. |
public void join(long miliseconds): | waits for a thread to die for the specified miliseconds. |
public int getPriority(): | returns the priority of the thread. |
public int setPriority(int priority): | changes the priority of the thread. |
public String getName(): | returns the name of the thread. |
public void setName(String name): | changes the name of the thread. |
public Thread currentThread(): | returns the reference of currently executing thread. |
public int getId(): | returns the id of the thread. |
public Thread.State getState(): | returns the state of the thread. |
public boolean isAlive(): | tests if the thread is alive. |
public void yield(): | causes the currently executing thread object to temporarily pause and allow other threads to execute. |
public void suspend(): | is used to suspend the thread(depricated). |
public void resume(): | is used to resume the suspended thread(depricated). |
public void stop(): | is used to stop the thread(depricated). |
public boolean isDaemon(): | tests if the thread is a daemon thread. |
public void setDaemon(boolean b): | marks the thread as daemon or user thread. |
public void interrupt(): | interrupts the thread. |
public boolean isInterrupted(): | tests if the thread has been interrupted. |
public static boolean interrupted(): | tests if the current thread has been interrupted. |
The Runnable interface should be implemented by any class whose instances are intended to be executed by a thread. Runnable interface have only one method named run().
Method name | Description |
---|---|
public void run(): | is used to perform action for a thread. |
The start() method of Thread class is used to start a newly created thread. It performs the following tasks:
class ExampleThread extends Thread {
public void run(){
System.out.println("thread is running...");
}
public static void main(String args[]){
ExampleThread t1=new ExampleThread();
t1.start();
}
}
package com.java.session.thirteen;
public class ThreadExample1 implements Runnable {
@Override
public void run() {
System.out.println("Started runnable interface....!");
}
public static void main(String[] args) {
ThreadExample1 t1 = new ThreadExample1();
t1.run();
}
}
Thread has join() method, this method is used to join the another thread once execution of current thread.
Example: In this example, we're creating a class RunnableDemo by implementing Runnable interface.
RunnableDemo class has run() method implementation. In main class TestThread, we've created the RunnableDemo
objects and using those objects we've created two Thread objects. When Thread.start() method is called on
each thread objects, threads start processing and program is executed. Using join() method, we're blocking
the current thread which ensure that once thread is complete then only next thread will start.
package com.java.session.thirteen;
public class TestThreadJoin {
public static void main(String[] args) throws InterruptedException {
Thread t1 = new Thread(new RunnableDemo(), "Thread-1");
Thread t2 = new Thread(new RunnableDemo(), "Thread-2");
Thread t3 = new Thread(new RunnableDemo(), "Thread-3");
t1.start();
t1.join();
t2.start();
t2.join();
t3.start();
}
}
class RunnableDemo implements Runnable {
@Override
public void run() {
System.out.println("Thread :: "+Thread.currentThread().getName()+" started");
for(int i=0; i<5; i++) {
System.out.println("Thread :: "+Thread.currentThread().getName()+ " i "+i+ " Running");
}
System.out.println("Thread :: "+Thread.currentThread().getName()+ " Dead");
}
}
Thread Scheduler is nothing but schudling a task multiple time for a specific period of time. Java provides a java.util.concurrent.ScheduledExecutorService interface which is a subinterface of ExecutorService interface, and it supports future periodic execution of tasks/threads.
Example: The following TestThread program shows usage of ScheduledExecutorService interface in thread based environment to schedule a task to run after 2 seconds at interval of 2 seconds in time period of 10 seconds showcasing usage of scheduleAtFixedRate() and schedule() methods.
package com.java.session.thirteen;
import java.util.concurrent.*;
public class ThreadSchedulerExample {
public static void main(String[] args) {
final ScheduledExecutorService scheduler = Executors.newScheduledThreadPool(1);
ScheduledFuture<?> beepHandler = scheduler.scheduleAtFixedRate(new BeepTask(), 0, 2, TimeUnit.SECONDS);
scheduler.schedule(new Runnable() {
@Override
public void run() {
beepHandler.cancel(true);
scheduler.shutdown();
}
}, 10, TimeUnit.SECONDS);
}
static class BeepTask implements Runnable {
@Override
public void run() {
System.out.println("Beep Executed...!");
}
}
}
A thread pool is a collection of pre-initialized threads. At any program start up if we want to create a pool of thread then will go with the concept called thread pool. This is mostly used in server side programming. Whenever a server started thread pool will be created and based on the request server will pick the available thread from the thread pool, once it's job is completed then it will return back to the pool. If the pool contains no accessible thread, the server waits till one becomes free.
4 different types of thread pool can be created. using below methods
Method | Description |
---|---|
public static ExecutorService newCachedThreadPool() | Creates a thread pool that creates new threads as needed, but will reuse previously constructed threads when they are available. |
public static ExecutorService newFixedThreadPool(int nThreads) | Creates a thread pool that reuses a fixed number of threads operating off a shared unbounded queue. |
public static ScheduledExecutorService newScheduledThreadPool(int corePoolSize) | Creates a thread pool that can schedule commands to run after a given delay, or to execute periodically. |
public static ExecutorService newWorkStealingPool() | Creates a work-stealing thread pool using all available processors as its target parallelism level. |
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
public class TestThread {
public static void main(final String[] arguments) throws InterruptedException {
ExecutorService executor = Executors.newFixedThreadPool(2);
// Cast the object to its class type
ThreadPoolExecutor pool = (ThreadPoolExecutor) executor;
//Stats before tasks execution
System.out.println("Largest executions: "
+ pool.getLargestPoolSize());
System.out.println("Maximum allowed threads: "
+ pool.getMaximumPoolSize());
System.out.println("Current threads in pool: "
+ pool.getPoolSize());
System.out.println("Currently executing threads: "
+ pool.getActiveCount());
System.out.println("Total number of threads(ever scheduled): "
+ pool.getTaskCount());
executor.submit(new Task());
executor.submit(new Task());
executor.submit(new Task());
executor.submit(new Task());
//Stats after tasks execution
System.out.println("Core threads: " + pool.getCorePoolSize());
System.out.println("Largest executions: "
+ pool.getLargestPoolSize());
System.out.println("Maximum allowed threads: "
+ pool.getMaximumPoolSize());
System.out.println("Current threads in pool: "
+ pool.getPoolSize());
System.out.println("Currently executing threads: "
+ pool.getActiveCount());
System.out.println("Total number of threads(ever scheduled): "
+ pool.getTaskCount());
executor.shutdown();
}
static class Task implements Runnable {
public void run() {
try {
Long duration = (long) (Math.random() * 5);
System.out.println("Running Task! Thread Name: " +
Thread.currentThread().getName());
TimeUnit.SECONDS.sleep(duration);
System.out.println("Task Completed! Thread Name: " +
Thread.currentThread().getName());
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
Whenever we run a Java program, main thread is created automatically. This thread is responsible for execution of java program. The main thread is created by the JVM automatically when a program starts. But you can control a Main thread by using different Thread methods and techniques.
package com.java.session.thirteen;
public class TestThread {
public void printName() {
System.out.println("Thread Name: " + Thread.currentThread().getName());
System.out.println("Thread Priority: " +Thread.currentThread().getPriority());
}
public static void main(String args[]) {
TestThread thread = new TestThread();
thread.printName();
}
}
Every Java thread has a priority that helps the operating system determine the order in which threads are scheduled. You can get and set the priority of a Thread. Thread class provides methods and constants for working with the priorities of a Thread. Threads with higher priority are more important to a program and should be allocated processor time before lower-priority threads. However, thread priorities cannot guarantee the order in which threads execute and are very much platform dependent.
Java thread priorities are in the range between MIN_PRIORITY (a constant of 1) and MAX_PRIORITY (a constant of 10). By default, every thread is given priority NORM_PRIORITY (a constant of 5).
package com.java.session.thirteen;
public class ThreadPriorityDemo {
public static void main(String[] args) {
ThreadDemo t1 = new ThreadDemo();
ThreadDemo t2 = new ThreadDemo();
ThreadDemo t3 = new ThreadDemo();
t1.setPriority(Thread.MAX_PRIORITY);
t2.setPriority(Thread.MIN_PRIORITY);
t3.setPriority(Thread.NORM_PRIORITY);
t1.start();
t2.start();
t3.start();
}
}
class ThreadDemo extends Thread {
public void run() {
System.out.println("ThreadName "+Thread.currentThread().getName()+" Priority "+Thread.currentThread().getPriority());
for(int i=0; i<4; i++) {
System.out.println("Thread: " + Thread.currentThread().getName() + ", " + i);
}
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
A Daemon thread is created to support the user threads. It generallty works in background and terminated once all the other threads are closed. Garbage collector is one of the example of Daemon thread.
Method | Description |
---|---|
Thread.setDaemon() Method | Marks this thread as either a daemon thread or a user thread. |
Thread.isDaemon() Method | Checks if this thread is a daemon thread. |
class ThreadDemo extends Thread {
ThreadDemo( ) {
}
public void run() {
System.out.println("Thread " + Thread.currentThread().getName()
+ ", is Daemon: " + Thread.currentThread().isDaemon());
}
public void start () {
super.start();
}
}
public class TestThread {
public static void main(String args[]) {
ThreadDemo thread1 = new ThreadDemo();
ThreadDemo thread2 = new ThreadDemo();
ThreadDemo thread3 = new ThreadDemo();
thread3.setDaemon(true);
thread1.start();
thread2.start();
thread3.start();
}
}