随着微服务架构的兴起,跨设备调用越来越频繁,一个业务流程,可能调用N次第三方接口,获取N种上游数据。因此,如何高效率地异步去调取这些接口,然后同步的去处理这些接口返回的结果?这是高并发要解决的一个基础问题。
在Netty中,大量使用了异步回调模式。
一、多线程join合并流程
A线程调用线程B的B.join方法,合并B线程。那么,线程A进入阻塞状态,知道B线程执行完成。
join方法的三个重载版本:
- void join():A线程等待B线程执行结束之后,A线程重新恢复执行。
- void join(long millis):最长等待时间,超过后。不论B线程是否结束,A线程重新恢复执行。
- void join(long mills,int nanos):最长等待时间-mills+nanos, 不论B线程是否结束,A线程重新恢复执行。
二、FutureTask异步回调
Callable接口:
- Runnable接口是在java多线程中表示线程的业务代码的抽象接口。但是,它的run()是没有返回值的。
- java定义了类似接口--Callable接口。代表业务处理的方法是call()。
- 区别:Callable接口不能作为Tread的target目标。
- 搭桥:FutrueTask使Callable可以作为Thread的target目标。是对Callable的二次封装。
FutrueTask:
- 搭桥,FutrueTask类能当做Thread的target目标。
- 获取,FutrueTask可以获取异步执行结果。
- 抽象,在java语言中,将FutrueTask的一系列操作抽象出来---Futrue接口。
Futrue接口:
- 判断:判断并发任务是否执行完成。
- 获取:获取并发的任务完成后的结果。
- 取消:取消并发执行中的任务。
-
public interface Future<V> { //取消并发任务的执行。 boolean cancel(booleanmayInterruptRunning); booleanisCancelled(); //获取并发任务的执行状态。如果任务执行结束,则返回true。 booleanisCancelled():获取并发任务的取消状态。如果任务完成前被取消,则返回true。 booleanisDone(); //获取并发任务执行的结果。注意,这个方法是阻塞性的。如果并发任务没有执行完成,调用此方法的线程会一直阻塞,直到并发任务执行完成。 V get() throws InterruptedException, ExecutionException; //获取并发任务执行的结果。也是阻塞性的,但是会有阻塞的时间限制,如果阻塞时间超过设定的timeout时间,该方法将抛出异常。 V get(long timeout, TimeUnitunit) throws InterruptedException, ExecutionException, TimeoutException; }
FutrueTask深入:
- private Callable callable;
- private Object outcome;
- run()
三、FutrueTask案例---同步回调
本FutrueTask案例缺点:虽然用了Futrue模式,但是只是能获取异步结果,依然需要等待,依然是阻塞的。
public class JavaFutureDemo {
public static final int SLEEP_GAP = 500;
public static String getCurThreadName() {
return Thread.currentThread().getName();
}
//第一步,实现了Callable,替代Runnable,实现线程业务-烧水。
static class Hot