In Java, Virtual threads are now supported by the Java Platform. Virtual threads are lightweight threads that greatly minimize the effort required to create, operate, and manage high volumes systems that are concurrent. As a result, they are more efficient and scalable than standard platform threads.
A thread is the smallest processing unit that can be scheduled. It operates concurrently with, and mostly independently of other units of this type. It's an instance of java.lang.Thread.
There are two kinds of threads, platform threads and virtual threads:
- Platform Threads
- Virtual Threads
1. Platform Threads
Operating system (OS) threads are implemented with a platform thread acting as a thin wrapper around them. Java code is executed by a platform thread on its parent OS thread, and the platform thread captures its OS thread for the length of its lifetime.
As a result, there can only be an equal number of OS threads and platform threads.
The operating system usually maintains a large thread stack and additional resources for platform threads. They may be in short supply, but they are suitable for executing many kinds of work.
2. Virtual Threads
A virtual thread is an instance of java.lang.Thread, independent of any OS thread, is used to run programs. The Java runtime suspends the virtual thread until it resumes when the code calls a blocked I/O operation. Virtual threads have a limited call stack and can only execute one HTTP client call or JDBC query. They are suitable for delayed operations, but not for extended CPU-intensive tasks.
Syntax of Virtual Threads:
Thread virtualThread = Thread.ofVirtual().start(() -> {
// Code to be executed by the virtual thread
});
Why Use Virtual Thread?
In your high quantities concurrent applications, use virtual threads if you have many concurrent processes that take a long time to finish. Server applications often handle large numbers of client requests, which requires blocking I/O tasks such as resource access. This makes server applications high-throughput.
Virtual threads do not execute code more quickly than platform threads. Their goal is to provide scale (greater throughput) rather than speed (lower latency).
Advantages of Java Virtual Threads:
There are various advantages to using virtual threads:
- Increases the availability of applications
- Enhances application throughput.
- Reduces the occurrence of 'OutOfMemoryError: Unable to Create New Native Thread'.
- Reduces the amount of memory used by the application
- Enhances code quality
- Platform Threads are completely compatible with them.
How To Create A Virtual Thread?
Platform and virtual thread creation is possible with the Thread and Thread.Builder APIs. The methods to build an ExecutorService that launches a new virtual thread for each operation are also defined in the java.util.concurrent.Executors class.
1. Using the Thread Class and the Thread.Builder Interface to Create a Virtual Thread
Create a version of Thread.Builder using the Thread.ofVirtual() function to build virtual threads.
The following example creates and opens a virtual thread that outputs a message. To wait for the virtual thread to finish its work, it calls the join method. You can see the written message before the main thread ends by doing this.
Thread thread = Thread.ofVirtual().start(() -> System.out.println("Hello"));
thread.join();
You can create threads with standard Thread properties, such as the thread name, using Thread.Builder. While Thread.Builder.OfVirtual creates virtual threads, Thread.Builder.OfPlatform creates platform threads.
The given code starts and opens a virtual thread called "MyThread," prints a message while it's operating, and then uses t.join() to wait for the thread to finish. You can follow these steps to a similar program:
Java
// Java program to demonstrate exchange
// Data between threads using scoped values
import java.util.*;
//Driver class
public class VirtualThreadExample {
// main function
public static void main(String[] args) {
try {
// Initialization of thread
Thread.Builder builder = Thread.ofVirtual().name("GFG Thread");
Runnable task = () -> {
System.out.println("Running thread");
};
Thread t = builder.start(task);
System.out.println("Thread t name: " + t.getName());
// Add a delay to allow the virtual thread to run
// Sleep for 1 second
Thread.sleep(1000);
// Wait for the thread to complete
t.join();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
Output:
Running thread
Thread t name: GFG Thread
Explanation of the above program:
- Using Thread.ofVirtual().name("MyThread"), we establish a virtual thread.
- Start the thread with a basic Runnable job that outputs "Running thread."
- We use t.getName() to print the thread's name after it has been started.
- To wait for the thread to finish, we use t.join().
- Any InterruptedException that might be generated while the thread is running is identified by us.
This software will launch a virtual thread, carry all the task, print the thread name, and then wait for the thread to terminate.
2. Creating and executing a virtual thread with the Executors.newVirtualThreadPerTaskExecutor() Method
You can separate the creation and management of threads from other software components by using executors.
The Executors.newVirtualThreadPerTaskExecutor() function is used in the example below to build the ExecutorService. To complete the work, a new virtual thread is generated and launched when you use ExecutorService.submit(Runnable). A Future instance is returned by this method. It's important to note that the Future.get() function waits for the thread to complete its task.
The code below code submits a basic task that prints a message and then uses future to wait for the task to finish using an ExecutorService with a virtual thread per task.fetch(). It prints "GeeksForGeeks" to signify that the task has been finished after it is finished.
This Java program represents the behavior in question:
Java
// Java Program for Creating and executing
// Virtual thread with the
// Executors.newVirtualThreadPerTaskExecutor() Method
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
public class VirtualThreadExecutorExample {
public static void main(String[] args) {
try (ExecutorService myExecutor = Executors.newVirtualThreadPerTaskExecutor()) {
// Submit a task that prints a message
Future<?> future = myExecutor.submit(() -> System.out.println("Running thread"));
// Wait for the task to complete
future.get();
System.out.println("Program Completed !!");
} catch (InterruptedException | ExecutionException e) {
e.printStackTrace();
}
}
}
Output:
Running thread
Program Completed !!
Explanation of the above program:
- We use virtual threads with executors to develop an executor service.virtualThreadPerTaskExecutor() is created.
- We submit a basic task that uses myExecutor to print "Running thread".submit(...) and take note of the Future object that the submission has returned.
- We employ future.get() to pause when the job is finished. This will keep blocking till the job is completed.
- "GeeksForGeeks" is printed to show that the task has been finished after it is finished.
- To handle any exceptions that might arise, we catch ExecutionException and InterruptedException.
Multithreaded Client Server
The example that follows has two classes. A server application called EchoServer listens on a specific port and launches a fresh virtual thread with each new connection. A client application called EchoClient establishes a connection with the server and transmits commands submitted via the command line.
EchoClient connects to EchoServer via establishing a socket. It receives user input via the standard input stream, reads it, and writes the text to the socket to send it to EchoServer.The input is transmitted back to the EchoClient by the EchoServer over the socket. EchoClient receives data from the server and reads and shows it.
- With virtual threads one for each client connection - EchoServer can serve numerous clients at once.
Below is the implementation of the above-mentioned topic:
Java
// Java Program to implement
// Multithreaded Client Server
import java.io.*;
import java.net.*;
//Driver class
public class EchoServer {
//Main method
public static void main(String[] args) throws IOException {
if (args.length != 1) {
System.err.println("Usage: java EchoServer <port>");
System.exit(1);
}
int portNumber = Integer.parseInt(args[0]);
try (ServerSocket serverSocket = new ServerSocket(portNumber)) {
System.out.println("EchoServer listening on port " + portNumber);
while (true) {
Socket clientSocket = serverSocket.accept();
// Accept incoming connections
// Start a service thread
Thread.ofVirtual().start(() -> {
try (
PrintWriter out = new PrintWriter(clientSocket.getOutputStream(), true);
BufferedReader in = new BufferedReader(new InputStreamReader(clientSocket.getInputStream()));
) {
String inputLine;
while ((inputLine = in.readLine()) != null) {
System.out.println("Received: " + inputLine);
out.println("Echo: " + inputLine);
out.flush(); // Explicitly flush the output
}
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
clientSocket.close();
} catch (IOException e) {
e.printStackTrace();
}
}
});
}
} catch (IOException e) {
System.out.println("Exception caught when trying to listen on port " + portNumber + " or listening for a connection");
System.out.println(e.getMessage());
}
}
}
Output:
Usage: java EchoServer <port>
What is the performance impact of Virtual threads?
Platform threads are much heavier than Java virtual threads. More details about Java virtual threads' impact on performance may be found here. However, to describe it briefly:
- Looking for virtual threads will save memory if your program uses a lot of threads or a large stack size.
- By using virtual threads instead of thread pools when your application often generates new threads, you can improve response time.
Similar Reads
Java IO Tutorial
Java programming language comes with a variety of APIs that helps the developers to code more efficiently. One of those APIs is Java IO API. Java IO API helps the users to read and write data. In simple words, we can say that the Java IO helps the users to take the input and produce output based on
15+ min read
run() Method in Java Thread
The run() method is available in the thread class constructed using a separate Runnable object. Otherwise, this method does nothing and returns. We can call the run() method multiple times. The run() method can be called in two ways which are as follows:Using the start() method.Using the run() metho
3 min read
Java Thread Class
Thread is a line of execution within a program. Each program can have multiple associated threads. Each thread has a priority which is used by the thread scheduler to determine which thread must run first. Java provides a thread class that has various method calls to manage the behavior of threads b
5 min read
Java Virtual Machine (JVM) Stack Area
The Java Virtual Machine is responsible for running Java applications, and it manages various memory areas, one of which is the Stack Area. In this article, we are going to discuss about JVM Stack Area in depth.In Java, each thread has its stack called the Run-Time Stack, created when the thread sta
4 min read
JRE in Java
Java Runtime Environment (JRE) is an open-access software distribution that has a Java class library, specific tools, and a separate JVM. In Java, JRE is one of the interrelated components in the Java Development Kit (JDK). It is the most common environment available on devices for running Java prog
4 min read
Shift Operator in Java
Operators in Java are used to performing operations on variables and values. Examples of operators: +, -, *, /, >>, <<. Types of operators: Arithmetic Operator,Shift Operator,Relational Operator,Bitwise Operator,Logical Operator,Ternary Operator andAssignment Operator. In this article, w
4 min read
Vector get() Method in Java
The java.util.vector.get() method is used to fetch or retrieve an element at a specific index from a Vector. Syntax: Vector.get(int index) Parameters: This method accepts a mandatory parameter index which is of integer data type. It specifies the position or index of the element to be fetched from t
2 min read
Java Tutorial
Java is a high-level, object-oriented programming language used to build web apps, mobile applications, and enterprise software systems. It is known for its Write Once, Run Anywhere capability, which means code written in Java can run on any device that supports the Java Virtual Machine (JVM).Java s
10 min read
Unnamed Patterns and Variables in Java
Java programming language offers multiple features that allow developers to write rich and concise code. Among these features, there are unnamed patterns and variables which enables developers to work with data in a more flexible and elegant way. In this article, we will study about unnamed patterns
4 min read
Super Keyword in Java
The super keyword in Java is a reference variable that is used to refer to the parent class when we are working with objects. You need to know the basics of Inheritance and Polymorphism to understand the Java super keyword. The Keyword "super" came into the picture with the concept of Inheritance. I
7 min read