Java多线程API调用并接受处理结果

最近一直学习多线程知识苦于没有机会运用到实际项目中,不过今天接到一个需求:请求发送多个第三方api请求,组合这些请求的返回结果返回给前端调用。如果说写for循环,单个请求结束后再继续调用下一个请求(自己想一想都蠢)。实在是体验效果不佳,需要优化api请求查询时间。
这里就能采用多线程异步请求多个Api,拿到所有结果后组合返回即可。话不多说,show code!

    @Test
    public void testThread2() {
        // 用来计算请求时间哒
        LocalDateTime beginTime = LocalDateTime.now();
        // ExecutorService fixPool = Executors.newFixedThreadPool(8);
        // 使用线程池而不是直接创建线程,这是因为创建线程代价很高,线程池可以有效地利用有限的线程来启动任务。
        // 手动创建线程池
        ThreadFactory namedThreadFactory = new ThreadFactoryBuilder()
                .setNameFormat("video-pool-%d").build();
        ExecutorService fixPool = new ThreadPoolExecutor(8, 10,
                0L, TimeUnit.MILLISECONDS,
                new LinkedBlockingQueue<>(1024), namedThreadFactory, new ThreadPoolExecutor.AbortPolicy());

        List<String> VIDEO_URL_LISTS = Lists.newArrayList("xxxx","xxxxx");
        List<String> resultList = Lists.newLinkedList();
        //申明数据回调处理类List>
        List<Future<String>> futures = new ArrayList<>();
        for (String videoId : VIDEO_URL_LISTS) {
            //申请单个线程执行类
            VideoThreadHandleThead call =new VideoThreadHandleThead(videoId);
            //提交单个线程
            Future<String> future = fixPool.submit(call);
            //将每个线程放入线程集合, 这里如果任何一个线程的执行结果没有回调,线程都会自动堵塞
            futures.add(future);
        }
        //所有线程执行完毕之后会执行下面的循环,然后通过循环每个个线程后执行线程的get()方法每个线程执行的结果
        for (Future<String> future : futures) {
            String json= null;
            try {
                json = future.get();
            } catch (InterruptedException | ExecutionException e) {
                fixPool.shutdown();
                log.error("界面初始化返回8个视频流url出现异常:{}",e.getMessage());
            }
            resultList.add(json);
        }
        // 当不再提交任何任务时,调用shutdown方法。
        fixPool.shutdown();
        
        Long timeConsuming = Duration.between(beginTime, LocalDateTime.now()).toMillis();
        //4053
        System.out.println("-----------"+timeConsuming);
    }
public class VideoThreadHandleThead implements Callable<String> {
    // 多个线程访问同一个方法的局部变量时,不会出现线程安全问题,
    // 因为局部变量存储在虚拟机栈中,属于线程私有的。
    private  String parameter;
    

    public VideoThreadHandleThead(String parameter) {
        this.parameter=parameter;
    }

    @Override
    public String call() {
        // 写业务
        JSONObject jsonBody = new JSONObject();
        jsonBody.put("streamType",0);
        jsonBody.put("cameraIndexCode",parameter);
        String body = jsonBody.toJSONString();
        //链式构建请求
        String videoJson = HttpRequest.post("xxxxxxx")
                .header(Header.ACCEPT, "*/*")//头信息,多个头信息多次调用此方法即可
                .body(body)//表单内容
                .timeout(20000)//超时,毫秒
                .execute().body();
        VideoUrlVo result = JSON.parseObject(videoJson, VideoUrlVo.class);
        if ( ("0").equals(result.getCode()) ){
            System.out.println(parameter+"请求结束!" );
            return  result.getData().getUrl();
        }
        return null;
    }
}

详细的说明都在代码里喽。 HttpRequest 源自于Hutool,我个人用的最顺手的Java工具类~强烈安利。
小伙伴们开发代码记得安装阿里巴巴编程规范插件(这里就提示我-须手动创建线程池)。为啥嘞,自己看一眼Executors.newFixedThreadPool的源码就知道啦,这里不再说明了。

你可能感兴趣的:(java多线程)