三、总结
1、以下为执行情况,从中可以看出执行50000条共耗时40分钟以内,速度比上一节中介绍的单线程效率提高了好几倍。
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; } } }