Asynchronous Programming - HolmesJJ/OOP-FP GitHub Wiki
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
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
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
Here is a simple example to implement a Thread
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;
}
}
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;
}
}
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