多线程请求百度接口实现地址转换经纬度(下)

本文涉及的产品
公网NAT网关,每月750个小时 15CU
简介: 多线程请求百度接口实现地址转换经纬度

三、总结

1、以下为执行情况,从中可以看出执行50000条共耗时40分钟以内,速度比上一节中介绍的单线程效率提高了好几倍。

image.png

2、下面为该类所有代码,可自行尝试。以上就是关于多线程请求百度接口实现地址转换经纬度的一些见解和实现,觉得不错的话,欢迎关注java基础笔记获取更多内容。

import cn.hutool.core.date.StopWatch;
import cn.hutool.core.text.csv.CsvWriter;
import com.google.common.collect.Maps;
import com.opencsv.CSVReader;
import com.opencsv.CSVReaderBuilder;
import org.springframework.boot.json.JacksonJsonParser;
import org.springframework.web.client.RestTemplate;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
/*
 *@create by jiankang
 *@date 2020/6/3 time 14:59
 */
public class GPSTestMe3 {
    private static String URL = "http://api.map.baidu.com/geocoding/v3/?address={address}&output=json&key=Krtc";
    private static RestTemplate restTemplate = new RestTemplate();
    private final static int AVALIABLE_PROCESSORS = Runtime.getRuntime().availableProcessors();
    private final static ThreadPoolExecutor POOL_EXECUTOR = new ThreadPoolExecutor(AVALIABLE_PROCESSORS, AVALIABLE_PROCESSORS * 2,
            1, TimeUnit.MINUTES, new LinkedBlockingQueue<>(5), new ThreadPoolExecutor.CallerRunsPolicy());
    public static void main(String[] args) {
        List<ResultBean> datas = Collections.synchronizedList(new ArrayList<>(35000));
        ResultBean title = new ResultBean("external_id", "address", "longitude", "latitude");
        datas.add(title);
        String sourcePath = "C:\\Users\\ForceClouds\\Desktop\\origin6.csv";
        String goalPath = "C:\\Users\\ForceClouds\\Desktop\\result-origin6.csv";
        StopWatch stopWatch = new StopWatch();
        stopWatch.start("经纬度转换运行程序");
        readCSV(datas, sourcePath);
        stopWatch.stop();
        System.out.println(stopWatch.prettyPrint());
        writeCSV(datas, goalPath);
    }
    public static void writeCSV(List<ResultBean> datas, String goalPath) {
        CsvWriter csvWriter = new CsvWriter(new File(goalPath));
        for (ResultBean data : datas) {
            csvWriter.write(new String[]{data.getExternal_id(), data.getAddress(), data.getLongitude(), data.getLatitude()});
        }
        csvWriter.close();
    }
    public static void readCSV(List<ResultBean> datas, String sourcePath) {
        List<ResultBean> failData = Collections.synchronizedList(new ArrayList<>());
        try (CSVReader csvReader = new CSVReaderBuilder(new BufferedReader(new InputStreamReader(new FileInputStream(new File(sourcePath)), "utf-8"))).build()) {
            final List<String[]> strings = csvReader.readAll();
            strings.remove(0);
            for (String[] next : strings) {
                POOL_EXECUTOR.submit(new Runnable() {
                    @Override
                    public void run() {
                        String address = next[1].replaceAll("\\s*", "");
                        ResultBean resultBean = new ResultBean(next[0], address, null, null);
                        //百度接口地址转换经纬度方法
                        try {
                            getLngLat(datas, failData, resultBean);
                        } catch (Exception e) {
                        }
                    }
                });
            }
            if (isEndTask()) {
                //关掉线程池
                POOL_EXECUTOR.shutdown();
                //失败数据再次请求百度接口,最多循环一千次,防止失败数据出现程序永不停止
                int i = 1000;
                while (failData.size() > 0 && i > 0) {
                    List<ResultBean> tempFailData = Collections.synchronizedList(new ArrayList<>(failData));
                    failData.clear();
                    for (ResultBean resultBean : tempFailData) {
                        try {
                            getLngLat(datas, failData, resultBean);
                        } catch (Exception e) {
                        }
                    }
                    System.out.println("重试剩余次数:" + i);
                    i--;
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            System.out.println("----------------------------------success records: "+(datas.size()-1));
            System.out.println("fail records:" + failData.size());
        }
    }
    public static boolean isEndTask() {
        while (true) {
            if (POOL_EXECUTOR.getActiveCount() == 0) {
                return true;
            }
        }
    }
    /**
     * 封装的获取经纬度方法
     *
     * @param datas
     * @param failData
     * @param resultBean
     */
    private static void getLngLat(List<ResultBean> datas, List<ResultBean> failData, ResultBean resultBean) {
        Map<String, String> map = Maps.newHashMap();
        map.put("address", resultBean.getAddress());
        String response = restTemplate.getForObject(URL, String.class, map);
        if (response != null && response.contains("lng") && response.contains("lat")) {
            final Map<String, Object> geocoderResult = new JacksonJsonParser().parseMap(response);
            Map location = (Map) ((Map) geocoderResult.get("result")).get("location");
            Double lng = (Double) location.get("lng");
            Double lat = (Double) location.get("lat");
            ResultBean bean = new ResultBean(resultBean.getExternal_id(), resultBean.getAddress(), String.valueOf(lng), String.valueOf(lat));
            datas.add(bean);
            if (datas.size() % 1000 == 0) {
                System.out.println("------------------已经转换成功: " + datas.size() + "条-----------------------------------------");
            }
        } else {
            failData.add(resultBean);
        }
    }
    static class ResultBean {
        private String external_id;
        //百度经纬度
        private String longitude;
        private String latitude;
        //address
        private String address;
        public ResultBean(String external_id, String address, String longitude, String latitude) {
            this.external_id = external_id;
            this.longitude = longitude;
            this.latitude = latitude;
            this.address = address;
        }
        public String getExternal_id() {
            return external_id;
        }
        public String getAddress() {
            return address;
        }
        public String getLongitude() {
            return longitude;
        }
        public String getLatitude() {
            return latitude;
        }
        public void setExternal_id(String external_id) {
            this.external_id = external_id;
        }
        public void setLongitude(String longitude) {
            this.longitude = longitude;
        }
        public void setLatitude(String latitude) {
            this.latitude = latitude;
        }
        public void setAddress(String address) {
            this.address = address;
        }
    }
}
相关实践学习
每个IT人都想学的“Web应用上云经典架构”实战
本实验从Web应用上云这个最基本的、最普遍的需求出发,帮助IT从业者们通过“阿里云Web应用上云解决方案”,了解一个企业级Web应用上云的常见架构,了解如何构建一个高可用、可扩展的企业级应用架构。
目录
相关文章
|
5月前
|
缓存 API 定位技术
使用Python调用百度地图API实现地址查询
使用Python调用百度地图API实现地址查询
296 0
|
5月前
|
Ubuntu 网络协议
百度搜索:蓝易云【ubuntu系统如何设置静态IP地址?】
现在,你已经成功在Ubuntu系统中设置了静态IP地址。系统将使用指定的静态IP地址进行网络连接。
60 0
|
5月前
|
应用服务中间件 nginx
百度搜索:蓝易云【HTTP请求是如何关联Nginx server{}块的?】
总结来说,Nginx中的 `server{}`块用于关联HTTP请求和虚拟主机,通过配置不同的 `server{}`块,可以实现多个域名或IP地址的请求分发和处理。这样,Nginx可以根据不同的请求来提供不同的服务和内容。
60 0
|
11月前
|
Java
百度搜索:蓝易云【hutool Http 工具发送POST请求的几种方式。】
以上是使用Hutool发送POST请求的几种方式。根据实际需求和代码复杂度,选择合适的方式来发送POST请求。
285 0
|
5月前
|
网络协议 Linux C++
Linux C/C++ 开发(学习笔记十一 ):TCP服务器(并发网络网络编程 一请求一线程)
Linux C/C++ 开发(学习笔记十一 ):TCP服务器(并发网络网络编程 一请求一线程)
99 0
|
3月前
|
云计算
云计算问题之线程请求的栈深度大于虚拟机所允许的深度如何解决
云计算问题之线程请求的栈深度大于虚拟机所允许的深度如何解决
27 1
|
3月前
|
存储 安全 Java
Java面试题:假设你正在开发一个Java后端服务,该服务需要处理高并发的用户请求,并且对内存使用效率有严格的要求,在多线程环境下,如何确保共享资源的线程安全?
Java面试题:假设你正在开发一个Java后端服务,该服务需要处理高并发的用户请求,并且对内存使用效率有严格的要求,在多线程环境下,如何确保共享资源的线程安全?
54 0
|
3月前
|
并行计算 安全 算法
Java面试题:Java内存管理与多线程并发处理,设计一个Java应用,该应用需要处理大量并发用户请求,同时要求对内存使用进行优化,如何通过垃圾回收机制优化内存使用?
Java面试题:Java内存管理与多线程并发处理,设计一个Java应用,该应用需要处理大量并发用户请求,同时要求对内存使用进行优化,如何通过垃圾回收机制优化内存使用?
33 0
|
4月前
|
JSON 前端开发 API
程序技术好文:百度网盘真实地址解析(告别下载百度网盘)
程序技术好文:百度网盘真实地址解析(告别下载百度网盘)
243 0
|
12月前
|
应用服务中间件 nginx
百度搜索:蓝易云 ,Nginx设置禁用 OPTIONS 请求以及允许跨域教程!
通过按照上述步骤,在Nginx中设置禁用OPTIONS请求和允许跨域。请确保在编辑Nginx配置文件时使用正确的服务器名称或IP地址。
92 0
下一篇
无影云桌面