-
@Service
-
@Slf4j
-
public
class WeatherServiceImpl implements IWeatherService {
-
@Resource
-
private WeatherServiceApi weatherServiceApi;
-
@Resource
-
private RedisTemplate redisTemplate;
-
@Value(
"${redis.weather}")
-
private Integer redisWeather;
-
private ThreadLocal<WeatherHourlyAndLifestyleNow> hourlyThreadLocal =
new ThreadLocal();
-
private ThreadLocal<WeatherDailyForecastAndLifestyleNow> dailyThreadLocal =
new ThreadLocal<>();
-
-
@Override
-
public WeatherHourlyAndLifestyleNow queryCurrentDayWeather(String location,String lifestyle) {
-
Long st = System.currentTimeMillis();
-
String weatherKey = RedisEnum.CpspWeather.LOCATION_LIFESTYLE_SAVE_HOURLY_WEATHER.getKey(location,lifestyle);
-
WeatherHourlyAndLifestyleNow data = (WeatherHourlyAndLifestyleNow)redisTemplate.opsForValue().get(weatherKey);
-
if (
null != data){
-
return data;
-
}
-
//data = new WeatherHourlyAndLifestyleNow();
-
OnTheDayHourlyWeatherThreadLocal onTheDayHourlyWeatherThreadLocal =
new OnTheDayHourlyWeatherThreadLocal(location,weatherServiceApi,redisTemplate,redisWeather,
null,
null,
true);
-
hourlyThreadLocal.set(onTheDayHourlyWeatherThreadLocal.queryCurrentDayWeather(location, lifestyle));
-
data = hourlyThreadLocal.get();
-
// CountDownLatch countDownLatch = new CountDownLatch(hourlyCountDownLatch);
-
// FutureTask weatherHourlyTask = new FutureTask(new WeatherHourlyTask(countDownLatch,location,weatherServiceApi,redisTemplate,redisWeather));
-
// FutureTask lifestyleTask = new FutureTask(new LifestyleTask(countDownLatch,location,weatherServiceApi,redisTemplate,redisWeather,lifestyle));
-
// FutureTask weatherForecastTask = new FutureTask(new WeatherForecastTask(countDownLatch,location,weatherServiceApi,redisTemplate,redisWeather,null,null,true));
-
// FutureTask airQualityTask = new FutureTask(new AirQualityTask(countDownLatch,location,weatherServiceApi,redisTemplate,redisWeather,null,null,true));
-
// ExecutorService executorService = Executors.newFixedThreadPool(hourlyCountDownLatch);
-
// executorService.submit(weatherHourlyTask);
-
// executorService.submit(lifestyleTask);
-
// executorService.submit(weatherForecastTask);
-
// executorService.submit(airQualityTask);
-
// Long ft = System.currentTimeMillis();
-
// log.debug("==> ft run consume time :{}, countDownLatch :{}",ft-st,countDownLatch);
-
// try {
-
// countDownLatch.await();
-
// data.setHourlyList((List<WeatherHourly>) weatherHourlyTask.get());
-
// data.setLifestyleNows((List<WeatherLifestyleNow>) lifestyleTask.get());
-
// WeatherDailyForecastVo dailyForecastVo = (WeatherDailyForecastVo)weatherForecastTask.get();
-
// if (null != dailyForecastVo){
-
// data.setDailyForecast(dailyForecastVo.getDailyForecastList().get(0));
-
// data.setBaseInfoVo(dailyForecastVo.getBaseInfoVo());
-
// }
-
// List<AirQuality> airQualityList = (List<AirQuality>)airQualityTask.get();
-
// if(!CollectionUtils.isEmpty(airQualityList)){
-
// data.setAirQuality(airQualityList.get(0));
-
// }
-
// } catch (InterruptedException | ExecutionException e) {
-
// log.error("error:",e);
-
// throw ExceptionEnum.QUERY_WEATHER_ERROR.getException();
-
// }finally {
-
// executorService.shutdown();
-
// }
-
if (
null == data){
-
redisTemplate.opsForValue().set(weatherKey,data,redisWeather,TimeUnit.SECONDS);
-
}
-
log.debug(
"");
-
Long ed = System.currentTimeMillis();
-
log.debug(
"===> weatherServiceImpl queryCurrentDayWeather consume time total : {}",ed - st);
-
log.debug(
"");
-
return data;
-
}
-
}
-
@Slf4j
-
public
class OnTheDayHourlyWeatherThreadLocal {
-
private String location;
-
private WeatherServiceApi weatherServiceApi;
-
private RedisTemplate redisTemplate;
-
private Integer redisWeather;
-
private String startDate;
-
private String endDate;
-
private Boolean onTheDay;
-
private
int hourlyCountDownLatch =
4;
-
private
static ThreadLocal<FutureTask> threadLocal =
new ThreadLocal();
-
private CountDownLatch countDownLatch =
new CountDownLatch(
4);
-
-
-
public OnTheDayHourlyWeatherThreadLocal(String location, WeatherServiceApi weatherServiceApi,
-
RedisTemplate redisTemplate, Integer redisWeather, String startDate, String endDate,
-
Boolean onTheDay){
-
this.location = location;
-
this.weatherServiceApi = weatherServiceApi;
-
this.redisTemplate = redisTemplate;
-
this.redisWeather = redisWeather;
-
this.startDate = startDate;
-
this.endDate = endDate;
-
this.onTheDay = onTheDay;
-
}
-
-
public WeatherHourlyAndLifestyleNow queryCurrentDayWeather(String location, String lifestyle) {
-
Long st = System.currentTimeMillis();
-
String weatherKey = RedisEnum.CpspWeather.LOCATION_LIFESTYLE_SAVE_HOURLY_WEATHER.getKey(location,lifestyle);
-
WeatherHourlyAndLifestyleNow data = (WeatherHourlyAndLifestyleNow)redisTemplate.opsForValue().get(weatherKey);
-
if (
null != data){
-
return data;
-
}
-
data =
new WeatherHourlyAndLifestyleNow();
-
-
FutureTask weatherHourlyTask =
new FutureTask(
new WeatherHourlyTask(countDownLatch,location,weatherServiceApi,redisTemplate,redisWeather));
-
FutureTask lifestyleTask =
new FutureTask(
new LifestyleTask(countDownLatch,location,weatherServiceApi,redisTemplate,redisWeather,lifestyle));
-
FutureTask weatherForecastTask =
new FutureTask(
new WeatherForecastTask(countDownLatch,location,weatherServiceApi,redisTemplate,redisWeather,
null,
null,
true));
-
FutureTask airQualityTask =
new FutureTask(
new AirQualityTask(countDownLatch,location,weatherServiceApi,redisTemplate,redisWeather,
null,
null,
true));
-
ExecutorService executorService = Executors.newFixedThreadPool(hourlyCountDownLatch);
-
executorService.submit(weatherHourlyTask);
-
executorService.submit(lifestyleTask);
-
executorService.submit(weatherForecastTask);
-
executorService.submit(airQualityTask);
-
try {
-
countDownLatch.await(
3,TimeUnit.SECONDS);
-
-
data.setHourlyList((List<WeatherHourly>) weatherHourlyTask.get());
-
data.setLifestyleNows((List<WeatherLifestyleNow>) lifestyleTask.get());
-
WeatherDailyForecastVo dailyForecastVo = (WeatherDailyForecastVo)weatherForecastTask.get();
-
if (
null != dailyForecastVo){
-
data.setDailyForecast(dailyForecastVo.getDailyForecastList().get(
0));
-
data.setBaseInfoVo(dailyForecastVo.getBaseInfoVo());
-
}
-
List<AirQuality> airQualityList = (List<AirQuality>)airQualityTask.get();
-
if(!CollectionUtils.isEmpty(airQualityList)){
-
data.setAirQuality(airQualityList.get(
0));
-
}
-
}
catch (InterruptedException | ExecutionException e) {
-
log.error(
"error:",e);
-
throw ExceptionEnum.QUERY_WEATHER_ERROR.getException();
-
}
finally {
-
executorService.shutdown();
-
}
-
Long ed = System.currentTimeMillis();
-
log.debug(
"===> WeatherHourlyThreadLocal queryCurrentDayWeather consume time total : {}",ed - st);
-
log.debug(
"");
-
return data;
-
}
-
}
其中一个FutureTask
-
@Slf4j
-
public
class AirQualityTask implements Callable<List<AirQuality>> {
-
private CountDownLatch countDownLatch;
-
private String location;
-
private WeatherServiceApi weatherServiceApi;
-
private RedisTemplate redisTemplate;
-
private Integer redisWeather;
-
private String startDate;
-
private String endDate;
-
private Boolean onTheDay;
-
-
public AirQualityTask (CountDownLatch countDownLatch,String location,WeatherServiceApi weatherServiceApi,
-
RedisTemplate redisTemplate,Integer redisWeather,String startDate,String endDate,Boolean onTheDay){
-
this.countDownLatch = countDownLatch;
-
this.location = location;
-
this.weatherServiceApi = weatherServiceApi;
-
this.redisTemplate = redisTemplate;
-
this.redisWeather = redisWeather;
-
this.startDate = startDate;
-
this.endDate = endDate;
-
this.onTheDay = onTheDay;
-
}
-
-
@Override
-
public List<AirQuality> call() throws Exception {
-
try{
-
Long st = System.currentTimeMillis();
-
List<AirQuality> forecastAirQuality =
null;
-
if (onTheDay){
-
startDate = LocalDate.now().toString();
-
forecastAirQuality = queryAirQualityForecast(location,startDate,startDate);
-
}
else{
-
forecastAirQuality = queryAirQualityForecast(location,startDate,startDate);
-
}
-
-
Long ed = System.currentTimeMillis();
-
log.debug(
"");
-
log.debug(
"==> AirQualityTask consume time :{},countDownLatch:{}",ed-st,countDownLatch);
-
return forecastAirQuality;
-
}
catch (Exception e){
-
throw e;
-
}
finally {
-
countDownLatch.countDown();
-
}
-
-
}
-
-
/**
-
* 获取未来几天空气质量预报 (第三方文档只写了 3-7天)
-
*
-
* @param location
-
* @param startDate 开始日期
-
* @param endDate 结束日期
-
*/
-
public List<AirQuality> queryAirQualityForecast(String location,String startDate, String endDate) {
-
LocalDate queryStart = DateUtil.stringTransLocalDate(startDate);
-
LocalDate queryEnd = DateUtil.stringTransLocalDate(endDate);
-
return queryForecastAir(location, queryStart, queryEnd);
-
}
-
-
private List<AirQuality> queryForecastAir(String location, LocalDate queryStart, LocalDate queryEnd) {
-
Long period = DateUtil.localDatePeriod(queryStart, queryEnd);
-
if (period >
9) {
-
throw
new BusinessException(ExceptionEnum.QUERY_OUT_RANGE);
-
}
-
boolean noCache =
false;
-
String redisKey =
null;
-
LocalDate startDate =
null;
-
List<AirQuality> list =
new ArrayList<>();
-
for (
int index =
0; index < period; index++) {
-
startDate = queryStart;
-
startDate = startDate.plusDays(index);
-
redisKey = RedisEnum.CpspWeather.LOCATION_DATE_SAVE_FORECAST_AIR_QUALITY.getKey(location, startDate.toString());
-
AirQuality airQuality = (AirQuality) redisTemplate.opsForValue().get(redisKey);
-
if (airQuality ==
null) {
-
list =
new ArrayList<>();
-
noCache =
true;
-
break;
-
}
else {
-
list.add(airQuality);
-
}
-
}
-
if (noCache) {
-
List<AirQuality> aqList = getAirQualityForecast(location, ServiceConstant.AIR_QUALITY_FORECAST);
-
if (CollectionUtils.isEmpty(aqList)) {
-
log.info(
"==> queryCacheDailyAir no data back!");
-
throw ExceptionEnum.CPSP_AIR_PARSE_ERROR.getException();
-
}
-
for (AirQuality aq : aqList) {
-
for (
int day =
0; day < period; day++) {
-
startDate = queryStart;
-
startDate = startDate.plusDays(day);
-
if (startDate.toString().equals(aq.getQualityDate())) {
-
list.add(aq);
-
}
-
}
-
//setRedisForecastAir(aq,location);
-
redisKey = RedisEnum.CpspWeather.LOCATION_DATE_SAVE_FORECAST_AIR_QUALITY.getKey(location, aq.getQualityDate());
-
RedisOpsForValueAsync redisOpsForValueAsync =
new RedisOpsForValueAsync(redisTemplate,redisWeather,redisKey,aq);
-
WeatherExecutorService executorService =
new WeatherExecutorService();
-
executorService.submit(redisOpsForValueAsync);
-
}
-
}
-
return list;
-
}
-
-
子线程的子线程这个注解是不起作用的,只有主线程的才会被spring管理
-
// @Async
-
// public void setRedisForecastAir(AirQuality aq,String location){
-
// String redisKey = RedisEnum.CpspWeather.LOCATION_DATE_SAVE_FORECAST_AIR_QUALITY.getKey(location, aq.getQualityDate());
-
// redisTemplate.opsForValue().set(redisKey, aq, redisWeather, TimeUnit.SECONDS);
-
// }
-
-
/**
-
* 查询未来几天空气质量 不包含当天
-
*
-
* @param location
-
* @param queryType
-
* @return
-
*/
-
private List<AirQuality> getAirQualityForecast(String location, String queryType) {
-
JSONObject response = weatherServiceApi.queryAirQualityForecast(location);
-
//log.debug("==> cpsp getAirQualityForecast response : {}", response);
-
if (Objects.isNull(response)) {
-
log.error(
"==> cpsp response is null!");
-
throw
new BusinessException(ExceptionEnum.CPSP_RESPONSE_TIMEOUT);
-
}
-
return CommonWeather.setAirQualityForecast(response,location);
-
}
-
}
转载:https://blog.csdn.net/datszhang/article/details/105599489
查看评论