CPP
1. Thread class
|
1. Create Thread Object, which is entity that can start execution
immediately after creation 2. Thread object created using thread class is 2a. Not copy construtible. //error: use of deleted function 2b. Not copy assignable. //error: use of deleted function |
- Thread calling method of class
#include <thread>
class A {
void test(int a) {
cout << a;
}
public:
void fun(int a) {
//if we start thread on static function,
//then this will not be passed
thread t1(&A::test, this, a);
t1.join();
}
};
int main() {
A obj;
obj.fun(1);
}
2. Using Functor
#include <thread>
#include <iostream>
#include <mutex>
#include <vector>
std::mutex m;
void fun(int tid) {
int a;
m.lock();
a += 5;
std::cout <<
"Thread: " <<
tid << ", a:
" << a << std::endl;
m.unlock();
}
int main() {
std::vector <std::thread> vecThreads;
for (int i = 0; i< 5; ++i) {
//Functor to create Threads
vecThreads.emplace_back(
[&]() {
fun(i);
}
);
}
for (auto& t : vecThreads)
t.join();
return 0;
}
Rust
1. std::thread::spawn
-
thread::spawn() takes a
closure
as an argument, which contains the code to be executed in the new
thread
3 ways to create threads using thread::spawn
| Methods | Description |
|---|---|
| 1. Normal Closure |
|
| 2. Scoped Threads(Borrow from env) |
Normal Threads cannot borrow from their environment, but scoped
threads can. Scoped threads are not required to joined: - Reason being, when scoped thread completes, its required to return the borrowed data
|
| 3. Move Closure |
The move keyword indicates that the closure will take ownership of
any variables it captures from its environment.
|
2. std::thread::Builder
-
Allows for more control over thread creation, such as setting stack size
or naming the thread
use std::thread;
let builder = thread::Builder::new().name("my_thread".into()).stack_size(32 * 1024);
let handle = builder.spawn(|| {
println!("Hello from a custom thread!");
}).unwrap();
handle.join().unwrap();
3. Asynchronous Frameworks (e.g., Tokio)
-
For asynchronous programming, you can use libraries like Tokio, which
allows you to spawn tasks on a runtime.
#[tokio::main]
async fn main() {
tokio::spawn(async {
println!("Hello from an async task!");
});
// Other async code...
}
Python
import threading, zipfile
class AsyncZip(threading.Thread):
def __init__(self, infile, outfile): # Constructor
threading.Thread.__init__(self)
self.infile = infile
self.outfile = outfile
def run(self):
f = zipfile.ZipFile(self.outfile, 'w', zipfile.ZIP_DEFLATED)
f.write(self.infile)
f.close()
print('Finished background zip of:', self.infile)
background = AsyncZip('mydata.txt', 'myarchive.zip')
background.start()
print('The main program continues to run in foreground.')
background.join() # Wait for the background task to finish
print('Main program waited until background was done.')
POSIX
#include <pthread.h>
#include <iostream>
using namespace std;
#define NUM_OF_THREADS 5
void* worker (void* arg) {
cout << "Thread: " << *((int*)arg) << " Created";
}
int main() {
pthread_t thread_id[NUM_OF_THREADS];
int thread_args[NUM_OF_THREADS], ret;
for (int i=0;i<NUM_OF_THREADS;++i) {
thread_args[i] = i;
ret = pthread_create(&thread_id[i], 0, worker, (void*)&thread_args[i]);
}
for (int i=0; i < NUM_OF_THREADS;++i)
pthread_join (thread_id[i], 0);
return 0;
}
Java
OS Thread (Platform Thread)
A platform thread maps 1:1 to an OS thread. The JVM asks the kernel to create a native thread. Use these for CPU-bound work or when you need a small, fixed pool of threads.
1. Runnable Interface
class test implements Runnable {
test() {
Thread cur = Thread.currentThread();
//1. Created child thread
Thread t = new Thread (this, "New thread");
//2. Started child thread.
//if start() is not called, Child Thread will not start
t.start();
try {
for (int i = 0; i < 6; ++i) {
//Parent process waits 1sec
System.out.println ("Parent Thread");
Thread.sleep(1000);
}
} catch (InterruptedException e) {
System.out.println ("Interrupted");
}
System.out.println ("exiting main thread");
}
public void run () {
try {
for (int i = 0; i < 3; ++i) {
//Child Thread waits 2sec
System.out.println ("Child Thread");
Thread.sleep(2000);
}
}
catch (InterruptedException e) {
System.out.println ("child interrupted");
}
System.out.println ("exiting child thread");
}
public static void main (String args[]) {
new test(); //1. Calls constructor
}
}
$ javac test.java
$ java test
$ java test
Parent Thread
Child Thread
Parent Thread
Child Thread
Parent Thread
Parent Thread
Child Thread
Parent Thread
Parent Thread
exiting child thread
exiting main thread
Green Thread (Virtual Thread) Java 21+
In Java 21+, lightweight user-space threads are called virtual threads (Project Loom). The JVM schedules many virtual threads on a small pool of platform (carrier) threads — the same M:N idea as classic green threads. They are cheap to create (millions are fine) and ideal for blocking I/O such as HTTP calls, DB queries, and file reads.
Requires Java 21+. On older JDKs, only platform threads
(new Thread(...)) were available.
1. Thread.startVirtualThread()
Simplest way — start one virtual thread with a Runnable.
// VirtualThreadStart.java — Java 21+
public class VirtualThreadStart {
public static void main(String[] args) throws InterruptedException {
// main starts a virtual thread and continues immediately
Thread vt = Thread.startVirtualThread(() -> {
System.out.println("Child: " + Thread.currentThread());
// VirtualThread [#21]/runnable
});
System.out.println("Main: " + Thread.currentThread());
// Main: Thread[#1,main,5,main]
vt.join(); // wait for virtual thread to finish
System.out.println("Main exiting");
}
}
$ javac --release 21 VirtualThreadStart.java
$ java VirtualThreadStart
2. Thread.ofVirtual()
Builder API — set a name, uncaught-exception handler, or inherit inheritable locals before starting.
// VirtualThreadBuilder.java — Java 21+
public class VirtualThreadBuilder {
public static void main(String[] args) throws InterruptedException {
Thread.Builder.OfVirtual builder = Thread.ofVirtual().name("worker-", 0);
Thread t1 = builder.start(() ->
System.out.println("t1: " + Thread.currentThread().getName())
);
// t1: worker-0
Thread t2 = Thread.ofVirtual()
.name("io-task")
.uncaughtExceptionHandler((th, ex) ->
System.err.println("Error in " + th.getName() + ": " + ex))
.start(() -> System.out.println("t2: io-task running"));
t1.join();
t2.join();
System.out.println("Main exiting");
}
}
$ javac --release 21 VirtualThreadBuilder.java
$ java VirtualThreadBuilder
3. Virtual thread factory
Create a ThreadFactory when an API expects a factory (e.g.
custom executors or libraries).
// VirtualThreadFactory.java — Java 21+
import java.util.concurrent.ThreadFactory;
public class VirtualThreadFactory {
public static void main(String[] args) throws InterruptedException {
ThreadFactory factory = Thread.ofVirtual().name("vt-", 0).factory();
// main uses the factory instead of calling startVirtualThread directly
Thread t1 = factory.newThread(() ->
System.out.println("t1: " + Thread.currentThread().getName())
);
Thread t2 = factory.newThread(() ->
System.out.println("t2: " + Thread.currentThread().getName())
);
t1.start();
t2.start();
t1.join();
t2.join();
System.out.println("Main exiting");
}
}
$ javac --release 21 VirtualThreadFactory.java
$ java VirtualThreadFactory
4. Executors.newVirtualThreadPerTaskExecutor()
Preferred for many short tasks — each submitted job runs on its own virtual thread. Use try-with-resources so the executor shuts down cleanly.
// VirtualThreadExecutor.java — Java 21+
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
public class VirtualThreadExecutor {
public static void main(String[] args) {
// main submits tasks; each task gets its own virtual thread
try (ExecutorService executor =
Executors.newVirtualThreadPerTaskExecutor()) {
for (int i = 0; i < 5; i++) {
int id = i;
executor.submit(() ->
System.out.println("task " + id + " on " + Thread.currentThread())
);
}
} // executor closes and waits for all tasks to finish
System.out.println("Main exiting");
}
}
$ javac --release 21 VirtualThreadExecutor.java
$ java VirtualThreadExecutor
OS thread vs green thread in Java:
new Thread(r).start() → platform thread (1 OS thread each).
Thread.startVirtualThread(r) or the virtual executor → green
thread (many share few carrier threads).
Windows
#include <windows.h>
#include <tchar.h>
#include <strsafe.h>
using namespace std;
DWORD WINAPI worker(LPVOID param) {
HANDLE hStdout = GetStdHandle(STD_OUTPUT_HANDLE);
int* data = (int*)param;
TCHAR buf[60];
DWORD dwChar;
StringCchPrintf(buf, 60, TEXT("val=%d"), *data);
WriteConsole(hStdout, buf, 10, &dwChar, nullptr);
return 0;
}
int _tmain() {
DWORD thread_id[5];
for (int i = 0; i < 5; ++i) {
CreateThread(
NULL, //Default security attributes
0, //Use default stack size
worker, //thread function
(void*)i, //argument to thread function
0, //Default creation flag
&thread_id[i]); //Thread identifier returned
}
}