(Tasks = Green Thread) != OS Thread

Tasks are not threads, these are light weight threads created by runtime.
These are non-blocking & task may or may not execute on seperate thread.
2 tasks run concurrently.

Creating Tasks

tokio::main macro we can create main async.
tokio::spawn() create concurrent task
tokio::spawn() //Green Thread tokio::task::spawn_blocking executor::block_on
- spawn Non-blocking tasks within tokio runtime
- Main thread will wait on JoinHandle(same as pthread_join)

use tokio::task;
async fn fun1() {
    tokio::time::delay_for (std::time::Duration::from_milli(5).await;
    println!("thread-1");
}
async fn fun2() {
    println!("thread-2");
}

// create main async.
#[tokio::main]
async fn main() {
    let mut JoinHandles: <Vec> = vec![];

    // Create concurrent task
    let handle1 = 
        task::spawn(async{ fun1().await });
    JoinHandles.push(handle1);
        
    let handle2 = 
        task::spawn(async{ fun2().await });
    JoinHandles.push(handle2);

    for i in JoinHandles {
        match i {
            Ok(_) => {
                println!("Task success");
            }
            Err(e) => {
                println!("Task fail");
            }
        }
    }
}
$ cargo run
thread-1
thread-2
                    
Spawn a blocking task into a separate thread from the Tokio runtime

use tokio::task;
fn fun() {
    println!("fun");
}

async fn fun(arg) {
    // 3. Call blocking or 
    // CPU-intensive function in seperate thread
    let threadpool_future = 
        task::spawn_blocking(||fun());
    todo!()
}

fn main() {
    //1. Start tokio runtime
    let mut rt:Runtime = 
        tokio::runtime::Runtime::new().unwrap();
    let local:LocalSet = 
        tokio::task::LocalSet::new();
    //2. Spawn a future
    local.block_on (&mut rt, async move {
        fun(arg).await
    });            
}
                    

use futures::executor::block_on;
async fn fun1() { 
    print!("fun1"); 
}
async fn fun2() { 
    print!("fun2"); 
}
fn main() {
    // main() blocks until 
    // fun1(),fun2() does not compelte
    block_on(fun1());                       
    block_on(fun2());
}
$ main.exe
fun1 fun2
                    

Comparison

spawn() vs spawn_blocking()

spawn() spawn_blocking()
What spawn Non-blocking tasks within tokio runtime spawn blocking tasks within tokio runtime
Where task is executed Within the Tokio runtime's event loop In separate thread from the Tokio runtime's thread pool
blocking no Yes. Perform CPU-bound or blocking operations without blocking the Tokio runtime's event loop

spawn() vs spawn_local()

spawn() spawn_local()
What spawns async task same
Where task is executed Spwaned Task can run on any thread managed by Tokio Task should run on same thread that called tokio::spawn_local()

block_on() vs spawn_blocking()

block_on() spawn_blocking()
What Run 1 future to completion and there is only thread within tokio
- There are no other tasks on tokio
This spawn a blocking task into a separate thread from the Tokio runtime's thread pool.
while there can be other non-blocking tasks on tokio runtime