Asynchronous Programming - HolmesJJ/OOP-FP GitHub Wiki

Definition

Asynchrony is to run a task that allows the program to continue without waiting for the evaluation completion of this task.

Four ways to implement asynchronous programming

  • Runnable
  • Callable
  • Thread
  • CompletableFuture

Runnable

public static void main(String[] args) {

    final long START_TIME = System.currentTimeMillis();

    System.out.println("Main Thread Start");
    System.out.println("Main Thread Id : " + Thread.currentThread());

    Runnable runnable = new Runnable() {
        @Override
        public void run() {
            System.out.println("Asynchronous Thread Start");
            System.out.println("Asynchronous Thread Id : " + Thread.currentThread());
            try {
                Thread.sleep(3000);
            } catch (InterruptedException e) {
                e.fillInStackTrace();
            };
            System.out.println("Hello World");
            System.out.println("Asynchronous Thread End");
        }
    };

    Thread t = new Thread(runnable);
    t.start();

    // Busy waiting
    // Do not end the main thread immediately,
    // otherwise the thread pool used by CompletableFuture
    // by default will be closed immediately
    while (t.isAlive()) {
        try {
            System.out.println("Processing in asynchronous thread... (" +
                    (System.currentTimeMillis() - START_TIME) + ")");
            Thread.sleep(1000);
        } catch (InterruptedException e) {
            e.fillInStackTrace();
        }
    }

    System.out.println("Main Thread End");
}

/* Output */
Main Thread Start
Main Thread Id : Thread[main,5,main]
Asynchronous Thread Start
Asynchronous Thread Id : Thread[Thread-0,5,main]
Processing in asynchronous thread... (22)
Processing in asynchronous thread... (1038)
Processing in asynchronous thread... (2041)
Hello World
Asynchronous Thread End
Main Thread End

Callable

public static void main(String[] args) {

    final long START_TIME = System.currentTimeMillis();

    System.out.println("Main Thread Start");
    System.out.println("Main Thread Id : " + Thread.currentThread());

    ExecutorService es = Executors.newSingleThreadExecutor();

    Future<String> f = es.submit(new Callable<String>() {
        @Override
        public String call() {
            System.out.println("Asynchronous Thread Start");
            System.out.println("Asynchronous Thread Id : " + Thread.currentThread());
            try {
                Thread.sleep(3000);
            } catch (InterruptedException e) {
                e.fillInStackTrace();
            };
            System.out.println("Hello World");
            System.out.println("Asynchronous Thread End");
            return "Hello World";
        }
    });

    // Busy waiting
    // Do not end the main thread immediately,
    // otherwise the thread pool used by CompletableFuture
    // by default will be closed immediately
    while (!f.isDone()) {
        try {
            System.out.println("Processing in asynchronous thread... (" +
                    (System.currentTimeMillis() - START_TIME) + ")");
            Thread.sleep(1000);
        } catch (InterruptedException e) {
            e.fillInStackTrace();
        }
    }

    System.out.println("Main Thread End");
}

/* Output */
Main Thread Start
Main Thread Id : Thread[main,5,main]
Asynchronous Thread Start
Asynchronous Thread Id : Thread[pool-1-thread-1,5,main]
Processing in asynchronous thread... (26)
Processing in asynchronous thread... (1040)
Processing in asynchronous thread... (2041)
Hello World
Asynchronous Thread End
Main Thread End

Thread

Here is a simple example to implement a Thread

Async.java

public class Async<T> {

    // doThis asynchronously executes the passed parameters
    // -> thenDoThis handles the execution result
    // -> join returns the final result
    
    // Return Result
    private T value;
    // Callback Interface
    private Function<T, T> listener;
    // Asynchronous Thread
    Thread thread;

    // 1. Asynchronous thread executes Supplier and returns the current Async object
    public Async<T> doThis(Supplier<T> supplier) {
        thread = new Thread(() -> {
            System.out.println("Asynchronous Thread Start");
            System.out.println("Asynchronous Thread Id : " + Thread.currentThread());
            this.value = supplier.get();
            System.out.println("Asynchronous Thread End");
        });
        this.thread.start();
        return this;
    }

    // Define the Function object, Function is a Callback
    public Async<T> thenDoThis(Function<T, T> listener) {
        this.listener = listener;
        return this;
    }

    // 2. After the asynchronous thread finishes executing Runnable, it starts to execute Function
    public T join() {
        try {
            this.thread.join();
            this.value = this.listener.apply(this.value);
        } catch (InterruptedException e) {};
        return this.value;
    }
}

UnitTask.java

public class UnitTask {

    private final int id;

    public UnitTask(int id) {
        this.id = id;
    }

    public int compute() {
        String name = Thread.currentThread().getName();
        try {
            System.out.println(name + " : start");
            Thread.sleep(id * 1000);
            System.out.println(name + " : end");
        } catch (InterruptedException e) {};

        return id;
    }

    public int sleep() {
        try {
            Thread.sleep(id * 1000);
        } catch (InterruptedException e) {};

        return id;
    }
}

Main.java

public class Main {
    public static void main(String[] args) {

        System.out.println("Main Thread Start");
        System.out.println("Main Thread Id : " + Thread.currentThread());

        int x = new Async<Integer>()
                .doThis(() -> new UnitTask(3).compute())
                .thenDoThis(y -> y + 1)
                .join();

        System.out.println(x);
        System.out.println("Main Thread End");
    }
}

/* Output */
Main Thread Start
Main Thread Id : Thread[main,5,main]
Asynchronous Thread Start
Asynchronous Thread Id : Thread[Thread-0,5,main]
Thread-0 : start
Thread-0 : end
Asynchronous Thread End
4
Main Thread End

CompletableFuture

CompletableFuture

⚠️ **GitHub.com Fallback** ⚠️