第一种:
package com.example.demo.test;
import org.apache.http.concurrent.FutureCallback;
import java.util.LinkedList;
import java.util.List;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;
public class CallBackTest {
public static List<String> mai1(List<String> stringList) throws InterruptedException {
//利用计数器阻塞主线程,在全部回调结束后再close(源码是继承了通道同步锁)
final CountDownLatch countDownLatch = new CountDownLatch(100000);
//线程池(事例中自定义了时间限制)
ExecutorService executorService = Executors.newFixedThreadPool(5);
FutureCallback<String> futureCallback = new FutureCallback<String>() {
@Override
public void completed(String s) {
stringList.add(s);
countDownLatch.countDown();
}
@Override
public void failed(Exception e) {
countDownLatch.countDown();
}
@Override
public void cancelled() {
countDownLatch.countDown();
}
};
for (int i = 0; i < 100000; i++) {
final Integer i1 = i;
executorService.execute(new Runnable() {
@Override
public void run() {
try {
Thread.sleep(1000);
futureCallback.completed(String.valueOf(i1));
} catch (InterruptedException e) {
e.printStackTrace();
}
}
});
}
//阻塞主线程,设置超时时间2分钟,避免因子线程处理异常而长时间一直等待
countDownLatch.await(2, TimeUnit.MINUTES);
//关闭
executorService.shutdown();
return stringList;
}
public static void main(String[] args) throws InterruptedException {
long l = System.currentTimeMillis();
List<String> stringList = new LinkedList<>();
List<String> stringList1 = mai1(stringList);
System.out.println(stringList1);
long l1 = System.currentTimeMillis() - l;
System.out.println(l1);
}
}
第二种:
package com.example.demo.test;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.Callable;
import java.util.concurrent.CountDownLatch;
public class CallableThread implements Callable<Map<String,Integer>> {
//传递进来的参数
int data;
private Map <String,Integer> map =new HashMap <String,Integer>();//定义需要返回的map
private final CountDownLatch latch ;
public CallableThread( int data, CountDownLatch latch) {
this.data = data;
this.latch = latch;
}
public Map<String,Integer> call() throws Exception {
try{
//每个参数手动增加100
data+=100;
map.put("data", data);
System.out.println("线程:"+Thread.currentThread().getName());
}catch(Exception e){
e.printStackTrace();
}finally{
latch.countDown();
}
return map;
}
}
package com.example.demo.test;
import org.jetbrains.annotations.NotNull;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.*;
public class ThreadTest {
public static void main(String[] args) {
final CountDownLatch latch = new CountDownLatch(5);
ExecutorService pool=Executors.newFixedThreadPool(5);
List list=new ArrayList();
try {
for(int j=0;j<5;j++){
Callable<Map<String, Integer>> c1 = new CallableThread(5,latch);
Future<Map<String,Integer>> f1=pool.submit(c1);
list.add(f1);
}
latch.await();
for(int i=0;i<list.size();i++){
Future<Map<String,Integer>> f1=(Future<Map<String, Integer>>) list.get(i);
System.out.println((Integer)f1.get().get("data"));
}
} catch (InterruptedException | ExecutionException e) {
e.printStackTrace();
}
}
}
公司异步调用的例子:
package com.bsj.util.map;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.bsj.util.DataUntil;
import com.bsj.util.ExceptionUtil;
import com.bsj.util.GeoUntil;
import org.apache.commons.lang.StringUtils;
import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.client.entity.DeflateDecompressingEntity;
import org.apache.http.client.entity.GzipDecompressingEntity;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.concurrent.FutureCallback;
import org.apache.http.entity.StringEntity;
import org.apache.http.util.EntityUtils;
import org.apache.log4j.Logger;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;
/**
* 地理位置工具类
*
* @author 杨小华
* @date 2018/5/3 16:54
* @since v3
*/
@Deprecated
public class OldMapUtil {
private static Logger logger = Logger.getLogger(OldMapUtil.class);
/**
* 公有的异步获取地址
*
* @param geoList
* @return java.util.List<com.bsj.util.map.MapDto>
* @author 杨小华
* @date 2018/5/3 16:54
* @since v3
*/
public static List<MapDto> handleCommonMap(List<MapDto> geoList) throws InterruptedException {
// 提前校验
if(geoList == null || geoList.isEmpty()) {
return new LinkedList<>();
}
//1.纠偏并排序
int geoSize = geoList.size();
MapDto mapDto = null;
for (int i = 0; i < geoSize; i++) {
mapDto = geoList.get(i);
// 纠偏
double[] latLon = GeoUntil.transform(mapDto.getLat(), mapDto.getLon());
mapDto.setLat(latLon[0]);
mapDto.setLon(latLon[1]);
}
//2.异步去获取地址
long t1 = System.currentTimeMillis();
JSONArray array = getAsyncAddress(geoList);
//重新排序
GeoUntil.geoListSort(array);
System.out.println("传入数量:" + geoSize + ",输出数量" + array.size() + "耗时:" + (System.currentTimeMillis() - t1));
// 3.对数据进行处理
return arrayToMapDtoList(array);
}
/**
* 返回数据处理
*
* @param array
* @return java.util.List<com.bsj.util.map.MapDto>
* @author 杨小华
* @date 2018/5/4 11:09
* @since v3
*/
private static List<MapDto> arrayToMapDtoList(JSONArray array) {
List<MapDto> geoAddressList = new LinkedList<>();
MapDto mapDto = null;
for (int i = 0; i < array.size(); i++) {
mapDto = new MapDto();
JSONObject object = (JSONObject) array.get(i);
JSONObject code = (JSONObject) object.get("regeocode");
Object tagObj = object.get("tag");
if(tagObj != null){
int tag = Integer.valueOf(tagObj.toString());
mapDto.setTag(tag);
}
StringBuilder str = new StringBuilder();
if (code != null) {
mapDto.setAddress(code.get("formatted_address").toString());
JSONArray roads = (JSONArray)code.get("roads");
if(roads != null && !roads.isEmpty()) {
for (int j = 0; j < roads.size(); j++) {
if (j == 0) {
str.append("(");
} else {
str.append(" ");
}
JSONObject roadObj = (JSONObject) roads.get(j);
str.append("在").append(roadObj.getString("name"))
.append("的").append(roadObj.getString("direction"))
.append("方向约").append((int) Math.floor(roadObj.getDouble("distance")))
.append("米");
}
str.append(")");
mapDto.setRoads(str.toString());
}
}
geoAddressList.add(mapDto);
}
return geoAddressList;
}
/**
* 异步获取地址
*
* @param geoList
* @return com.alibaba.fastjson.JSONArray
* @author 杨小华
* @date 2018/5/4 10:24
* @since v3
*/
private static JSONArray getAsyncAddress(List<MapDto> geoList) throws InterruptedException {
JSONArray allList = new JSONArray();
List<List<MapDto>> splitData = DataUntil.splitData(geoList, 100);
//利用计数器阻塞主线程,在全部回调结束后再close
final CountDownLatch countDownLatch = new CountDownLatch(splitData.size());
//回调
FutureCallback<HttpResponse> callback = new FutureCallback<HttpResponse>() {
@Override
public void completed(final HttpResponse response) {
// System.out.println("成功线程 callback thread id is : " + Thread.currentThread().getId());
try {
HttpEntity httpEntity = response.getEntity();
// gzip 另外处理,否则乱码
if (httpEntity.getContentEncoding() != null) {
if ("gzip".equalsIgnoreCase(httpEntity.getContentEncoding().getValue())) {
httpEntity = new GzipDecompressingEntity(httpEntity);
} else if ("deflate".equalsIgnoreCase(httpEntity.getContentEncoding().getValue())) {
httpEntity = new DeflateDecompressingEntity(httpEntity);
}
}
// 取出应答字符串
String resultStr = EntityUtils.toString(httpEntity, "UTF-8");
//判断值返回是否正确
if (StringUtils.isNotEmpty(resultStr)) {
Object o = GeoUntil.handleGeo(resultStr);
if (o != null) {
JSONArray list = (JSONArray) o;
allList.addAll(list);
}else{
logger.error("@@返回解析为空的值:" + resultStr);
}
}else{
logger.error("@@返回空的值:" + resultStr);
}
} catch (Exception e) {
logger.error("MapUtil异步查询失败:" + ExceptionUtil.getStackStr(e));
}
//计数器减,执行完再减,否则会出现数据少100条的情况
countDownLatch.countDown();
}
@Override
public void failed(final Exception ex) {
//计数器减
countDownLatch.countDown();
System.out.println("失败线程callback thread id is : " + Thread.currentThread().getId() + ",error:" + ex);
}
@Override
public void cancelled() {
//计数器减
countDownLatch.countDown();
System.out.println("取消线程callback thread id is : " + Thread.currentThread().getId());
}
};
HttpAsyncUtil util = new HttpAsyncUtil();
String url = "http://120.76.69.92:8080/geo/GetGeo.json?";
// String url = PropertiesUtil.getConfig("servicesGeoUrl");
ExecutorService fixedThreadPool = Executors.newFixedThreadPool(5);
for (List<MapDto> mapDtoList : splitData) {
// 使用线程池,1w条 提升5秒左右
fixedThreadPool.execute(new Runnable() {
@Override
public void run() {
// 异步发送
Map<String, Object> param = new HashMap<>();
param.put("posList", mapDtoList);
String paramStr = "param=" + JSON.toJSONString(param);
paramStr = paramStr + "&jsoncallback=";
final HttpPost httpPost = new HttpPost(url);
StringEntity stringEntity = new StringEntity(paramStr, "utf-8");
httpPost.setEntity(stringEntity);
util.sendHttpPost(httpPost, callback);
}
});
}
//阻塞主线程,设置超时时间2分钟,避免因子线程处理异常而长时间一直等待
countDownLatch.await(2, TimeUnit.MINUTES);
//关闭
fixedThreadPool.shutdown();
util.close();
return allList;
}
public static void main(String[] args) throws InterruptedException {
List<MapDto> geoList = new LinkedList<>();
for (int i = 0; i < 10000; i++) {
MapDto mapDto = new MapDto();
mapDto.setLat(23.32004);
mapDto.setLon(114.01560);
mapDto.setTag(1+i);
geoList.add(mapDto);
}
List<MapDto> mapDtos = handleCommonMap(geoList);
int index = 0;
for(MapDto dto : mapDtos){
String address = dto.getAddress();
if(!"广东省惠州市博罗县罗浮山管委会544乡道".equals(address)){
System.out.println(address);
index ++;
}
}
System.err.println("错误的:" + index);
System.out.println(mapDtos == null ? 0 : mapDtos.size());
}
}
http调用:
package com.bsj.util.map;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.bsj.util.DataUntil;
import com.bsj.util.ExceptionUtil;
import com.bsj.util.GeoUntil;
import org.apache.commons.lang.StringUtils;
import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.client.entity.DeflateDecompressingEntity;
import org.apache.http.client.entity.GzipDecompressingEntity;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.concurrent.FutureCallback;
import org.apache.http.entity.StringEntity;
import org.apache.http.util.EntityUtils;
import org.apache.log4j.Logger;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;
/**
* 地理位置工具类
*
* @author 杨小华
* @date 2018/5/3 16:54
* @since v3
*/
@Deprecated
public class OldMapUtil {
private static Logger logger = Logger.getLogger(OldMapUtil.class);
/**
* 公有的异步获取地址
*
* @param geoList
* @return java.util.List<com.bsj.util.map.MapDto>
* @author 杨小华
* @date 2018/5/3 16:54
* @since v3
*/
public static List<MapDto> handleCommonMap(List<MapDto> geoList) throws InterruptedException {
// 提前校验
if(geoList == null || geoList.isEmpty()) {
return new LinkedList<>();
}
//1.纠偏并排序
int geoSize = geoList.size();
MapDto mapDto = null;
for (int i = 0; i < geoSize; i++) {
mapDto = geoList.get(i);
// 纠偏
double[] latLon = GeoUntil.transform(mapDto.getLat(), mapDto.getLon());
mapDto.setLat(latLon[0]);
mapDto.setLon(latLon[1]);
}
//2.异步去获取地址
long t1 = System.currentTimeMillis();
JSONArray array = getAsyncAddress(geoList);
//重新排序
GeoUntil.geoListSort(array);
System.out.println("传入数量:" + geoSize + ",输出数量" + array.size() + "耗时:" + (System.currentTimeMillis() - t1));
// 3.对数据进行处理
return arrayToMapDtoList(array);
}
/**
* 返回数据处理
*
* @param array
* @return java.util.List<com.bsj.util.map.MapDto>
* @author 杨小华
* @date 2018/5/4 11:09
* @since v3
*/
private static List<MapDto> arrayToMapDtoList(JSONArray array) {
List<MapDto> geoAddressList = new LinkedList<>();
MapDto mapDto = null;
for (int i = 0; i < array.size(); i++) {
mapDto = new MapDto();
JSONObject object = (JSONObject) array.get(i);
JSONObject code = (JSONObject) object.get("regeocode");
Object tagObj = object.get("tag");
if(tagObj != null){
int tag = Integer.valueOf(tagObj.toString());
mapDto.setTag(tag);
}
StringBuilder str = new StringBuilder();
if (code != null) {
mapDto.setAddress(code.get("formatted_address").toString());
JSONArray roads = (JSONArray)code.get("roads");
if(roads != null && !roads.isEmpty()) {
for (int j = 0; j < roads.size(); j++) {
if (j == 0) {
str.append("(");
} else {
str.append(" ");
}
JSONObject roadObj = (JSONObject) roads.get(j);
str.append("在").append(roadObj.getString("name"))
.append("的").append(roadObj.getString("direction"))
.append("方向约").append((int) Math.floor(roadObj.getDouble("distance")))
.append("米");
}
str.append(")");
mapDto.setRoads(str.toString());
}
}
geoAddressList.add(mapDto);
}
return geoAddressList;
}
/**
* 异步获取地址
*
* @param geoList
* @return com.alibaba.fastjson.JSONArray
* @author 杨小华
* @date 2018/5/4 10:24
* @since v3
*/
private static JSONArray getAsyncAddress(List<MapDto> geoList) throws InterruptedException {
JSONArray allList = new JSONArray();
List<List<MapDto>> splitData = DataUntil.splitData(geoList, 100);
//利用计数器阻塞主线程,在全部回调结束后再close
final CountDownLatch countDownLatch = new CountDownLatch(splitData.size());
//回调
FutureCallback<HttpResponse> callback = new FutureCallback<HttpResponse>() {
@Override
public void completed(final HttpResponse response) {
// System.out.println("成功线程 callback thread id is : " + Thread.currentThread().getId());
try {
HttpEntity httpEntity = response.getEntity();
// gzip 另外处理,否则乱码
if (httpEntity.getContentEncoding() != null) {
if ("gzip".equalsIgnoreCase(httpEntity.getContentEncoding().getValue())) {
httpEntity = new GzipDecompressingEntity(httpEntity);
} else if ("deflate".equalsIgnoreCase(httpEntity.getContentEncoding().getValue())) {
httpEntity = new DeflateDecompressingEntity(httpEntity);
}
}
// 取出应答字符串
String resultStr = EntityUtils.toString(httpEntity, "UTF-8");
//判断值返回是否正确
if (StringUtils.isNotEmpty(resultStr)) {
Object o = GeoUntil.handleGeo(resultStr);
if (o != null) {
JSONArray list = (JSONArray) o;
allList.addAll(list);
}else{
logger.error("@@返回解析为空的值:" + resultStr);
}
}else{
logger.error("@@返回空的值:" + resultStr);
}
} catch (Exception e) {
logger.error("MapUtil异步查询失败:" + ExceptionUtil.getStackStr(e));
}
//计数器减,执行完再减,否则会出现数据少100条的情况
countDownLatch.countDown();
}
@Override
public void failed(final Exception ex) {
//计数器减
countDownLatch.countDown();
System.out.println("失败线程callback thread id is : " + Thread.currentThread().getId() + ",error:" + ex);
}
@Override
public void cancelled() {
//计数器减
countDownLatch.countDown();
System.out.println("取消线程callback thread id is : " + Thread.currentThread().getId());
}
};
HttpAsyncUtil util = new HttpAsyncUtil();
String url = "http://120.76.69.92:8080/geo/GetGeo.json?";
// String url = PropertiesUtil.getConfig("servicesGeoUrl");
ExecutorService fixedThreadPool = Executors.newFixedThreadPool(5);
for (List<MapDto> mapDtoList : splitData) {
// 使用线程池,1w条 提升5秒左右
fixedThreadPool.execute(new Runnable() {
@Override
public void run() {
// 异步发送
Map<String, Object> param = new HashMap<>();
param.put("posList", mapDtoList);
String paramStr = "param=" + JSON.toJSONString(param);
paramStr = paramStr + "&jsoncallback=";
final HttpPost httpPost = new HttpPost(url);
StringEntity stringEntity = new StringEntity(paramStr, "utf-8");
httpPost.setEntity(stringEntity);
util.sendHttpPost(httpPost, callback);
}
});
}
//阻塞主线程,设置超时时间2分钟,避免因子线程处理异常而长时间一直等待
countDownLatch.await(2, TimeUnit.MINUTES);
//关闭
fixedThreadPool.shutdown();
util.close();
return allList;
}
public static void main(String[] args) throws InterruptedException {
List<MapDto> geoList = new LinkedList<>();
for (int i = 0; i < 10000; i++) {
MapDto mapDto = new MapDto();
mapDto.setLat(23.32004);
mapDto.setLon(114.01560);
mapDto.setTag(1+i);
geoList.add(mapDto);
}
List<MapDto> mapDtos = handleCommonMap(geoList);
int index = 0;
for(MapDto dto : mapDtos){
String address = dto.getAddress();
if(!"广东省惠州市博罗县罗浮山管委会544乡道".equals(address)){
System.out.println(address);
index ++;
}
}
System.err.println("错误的:" + index);
System.out.println(mapDtos == null ? 0 : mapDtos.size());
}
}