Future结合RxJava 实现异步调用

0 概述

在实际工作中,时常会遇到一个接口服务会调用很多其他的服务(10几个甚至更多,这些服务之间大多都不是相互依赖的),如果采用串行化调用,那么这个接口的服务rt(response time)就会很高,20*50ms=1000ms(假设该接口服务需要调用20个服务,平均每个服务rt为50ms)。本文主要给出Future结合Rxjava 实现异步化调用。(需要调用的服务方支持异步化调用)。

1 异步化调用

用户信息的异步查询,需要你调用服务支持异步调用~

@Component
public class UserServiceManager {
    @Autowired
    private UserService userService;

    /**
     * 根据userId异步查询用户信息
     *
     * @param userIds
     * @return 用户Id和User映射
     */
    public Single<Map<Long, User>> asynGetUserInfoMap(final Set<Long> userIds) {
        if (userIds == null || userIds.isEmpty()) {
            return null;
        }
        //todo
        Future<List<User>> resultFuture = null;//需要服务支持异步化调用

//通过Rxjava 发射出去
        return Single.from(new AsyncResponseFuture<List<User>, Map<Long, User>>(resultFuture) {
            @Override
            public Map<Long, User> process(List<User> response) {
                Map<Long, User> retMap = new HashMap<>();
                if (response == null ) {
                    return retMap;
                }
                for (User u : response) {
                    retMap.put(u.getUserId(), u);
                }
                return retMap;
            }
        }, 2000, TimeUnit.MILLISECONDS);
    }
}
public abstract class AsyncResponseFuture<P,R> implements Future<R> {

    private Future<P> future;

    @Override
    public boolean cancel(boolean mayInterruptIfRunning) {
        return false;
    }

    @Override
    public boolean isCancelled() {
        return false;
    }

    public AsyncResponseFuture(Future<P> future) {
        this.future = future;
    }

    @Override
    public boolean isDone() {
        return future.isDone();
    }

    @Override
    public R get() throws InterruptedException, ExecutionException {
        return null;
    }

    @Override
    public R get(long timeout, TimeUnit unit) throws InterruptedException, ExecutionException, TimeoutException {
        P response=future.get(timeout,unit);
        return process(response);
    }
    //处理相应的业务逻辑
    public abstract R process(P response);

}

2 获取数据工具实现类

import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import rx.Single;
import rx.functions.Action1;

import java.util.List;
import java.util.Map;
import java.util.concurrent.TimeoutException;

/**
 * 异步工具类
 */
public class AsyncUtils {

    private static final  Logger logger = LoggerFactory.getLogger(AsyncUtils.class);
    private static final String TIME_OUT_DESC = "timeout subscribe fail msg[%s]";
    private static final String SUBSCRIBE_FAIL_DESC = "subscribe fail msg[%s]";

    //获取单个对象 mgs 用于日志标识
    public static <T> T getObject(Single<T> source, final String msg) {
        final InnerReturn<T> innerValue = new InnerReturn<>();
        if (source == null) {
            return null;
        }
        source.subscribe(new Action1<T>() {
            @Override
            public void call(T t) {
                innerValue.setValue(t);
            }
        }, new Action1<Throwable>() {
            @Override
            public void call(Throwable e) {
                if (e != null && e instanceof TimeoutException) {
                    logger.error(String.format(TIME_OUT_DESC, msg));
                } else {
                    logger.error(String.format(SUBSCRIBE_FAIL_DESC, msg), e);
                }
            }
        });
        return innerValue.getValue();
    }

    //获取list 对象    mgs 用于日志标识
    public static <T> List<T> getList(Single<List<T>> source, final String msg) {
        final List<T> results = Lists.newArrayList();
        if (source != null) {
            source.subscribe(new Action1<List<T>>() {
                @Override
                public void call(List<T> t) {
                    if (t != null) {
                        results.addAll(t);
                    }
                }
            }, new Action1<Throwable>() {
                @Override
                public void call(Throwable e) {
                    if (e instanceof TimeoutException) {
                        logger.error(String.format(TIME_OUT_DESC, msg));
                    } else {
                        logger.error(String.format(SUBSCRIBE_FAIL_DESC, msg), e);
                    }
                }
            });
        }
        return results;
    }

    //获取Map 对象    mgs 用于日志标识
    public static <K, V> Map<K, V> getMap(Single<Map<K, V>> source, final String msg) {
        final Map<K, V> results = Maps.newConcurrentMap();
        if (source != null) {
            source.subscribe(new Action1<Map<K, V>>() {
                @Override
                public void call(Map<K, V> t) {
                    if (t != null) {
                        results.putAll(t);
                    }
                }
            }, new Action1<Throwable>() {
                @Override
                public void call(Throwable e) {
                    if (e instanceof TimeoutException) {
                        logger.error(String.format(TIME_OUT_DESC, msg));
                    } else {
                        logger.error(String.format(SUBSCRIBE_FAIL_DESC, msg), e);
                    }
                }
            });
        }
        return results;
    }

    public static <K, V> Map<K, V> getBatchMap(List<Single<Map<K, V>>> sources, final String msg) {
        final Map<K, V> results = Maps.newHashMap();
        if (sources != null && !sources.isEmpty()) {
            for (Single<Map<K, V>> source : sources) {
                Map<K, V> result = getMap(source, msg);
                if (result != null) {
                    results.putAll(result);
                }
            }
        }
        return results;
    }


    private static class InnerReturn<T> {
        private T value;

        public InnerReturn() {
        }

        public T getValue() {
            return value;
        }

        public void setValue(T value) {
            this.value = value;
        }

    }

    public static void main(String[] args) {
        if(null instanceof AsyncUtils)
        {
            System.out.print(false);
        }
    }
}

3 测试使用

@Service
public class TestService {
    @Autowired
    private UserServiceManager userService;

    private final Logger logger = LoggerFactory.getLogger(this.getClass());

    public void test() {
        Set<Long> set=new HashSet<>();
        set.add(12314L);
        set.add(142114L);
        //调用时候不会阻塞
        Single<Map<Long, User>> singleUserMap1 = userService.asynGetUserInfoMap(set);
        System.out.print("异步调用");
        Single<Map<Long, User>> singleUserMap2 = userService.asynGetUserInfoMap(set);

        //获取数据时候会阻塞
        Map<Long,User> userMap1=AsyncUtils.getMap(singleUserMap1,"singleUserMap");
        Single<Map<Long, User>> userMap2 = userService.asynGetUserInfoMap(set);
    } }
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值