CPP

1. Thread class


#include <thread>
#include <iostream>
void fun(int a){
    std::cout << "Hello";
}
int main() { 
    int a = 10;
    std::thread t1(fun, a);   //1
    t1.join();

    //std::thread t2 = t1     //2a

    // std::thread t2(fun,3); //2b
}
              
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

$ cat main.rs
use std::thread;
fn fun1() {
    println!("Thread-1");
}
fn main() {
    let handle1 = thread::spawn(fun1);      //Thread-1

    let handle2 = thread::spawn(||{         //Thread-2
            println! ("Thread-2");
        });

    // Thread1, Thread2 are joinable.
    // main will not exit without t1,t2
    // spawn() returns Struct std::thread::JoinHandle 
    // which has method join() 
    handle1.join().unwrap();
    handle2.join().unwrap();
}
$ cargo run
                
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

fn main() {
    let a = 1;

    thread::scope(|scope| {
        scope.spawn(|| {
            println!("{}", a);
        });
    });
}
3. Move Closure The move keyword indicates that the closure will take ownership of any variables it captures from its environment.

use std::thread;

fn main() {
    let a = 10;
    let handle = thread::spawn(move || {
        println!("Thread {}", a);
    });

    handle.join().unwrap(); // Wait for the thread to finish
}
                    

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
      }
    }