在请求api接口的时候,通常进行查询都会有时间设置,比如请求商品的修改时间。需要请求的时间区域并不确定,可能比较长,也可能比较短。这时候,希望有一种方式能根据时间的长短能自动划分区域,在请求量 和 请求次数中做一个平衡。这个时候,最好根据时间长短来划分合理的请求区域。
一个划分的demo:
import com.google.common.collect.Lists;
import io.vavr.Tuple;
import io.vavr.Tuple2;
import org.apache.commons.collections4.CollectionUtils;
import java.time.Duration;
import java.time.ZoneId;
import java.time.ZonedDateTime;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.ForkJoinPool;
import java.util.concurrent.RecursiveTask;
import java.util.function.BiFunction;
import java.util.function.Function;
/**
* @author yaoqiang
* @date 2021/2/5 09:09
* @description //TODO
*/
public class TimeDivisionTask<T> extends RecursiveTask<List<T>> {
/**
* 本任务的开始时间
*/
private final ZonedDateTime start;
/**
* 本任务的结束时间
*/
private final ZonedDateTime end;
/**
* 如何使用划分出来的时间
*/
private final BiFunction<ZonedDateTime, ZonedDateTime, List<T>> executeFun;
public TimeDivisionTask(ZonedDateTime start,
ZonedDateTime end,
BiFunction<ZonedDateTime, ZonedDateTime, List<T>> executeFun) {
this.start = start;
this.end = end;
this.executeFun = executeFun;
}
@Override
protected List<T> compute() {
long days = Duration.between(start, end).toDays();
if (days > 0) {
Tuple2<ZonedDateTime, List<T>> nextTime = doLoop(start, days, z -> z.plusDays(1), executeFun);
TimeDivisionTask<T> nextFork = new TimeDivisionTask<>(nextTime._1, end, executeFun);
nextFork.fork();
nextTime._2.addAll(nextFork.join());
return nextTime._2;
}
long hours = Duration.between(start, end).toHours();
if (hours > 0) {
Tuple2<ZonedDateTime, List<T>> nextTime = doLoop(start, hours, z -> z.plusHours(1), executeFun);
TimeDivisionTask<T> nextFork = new TimeDivisionTask<>(nextTime._1, end, executeFun);
nextFork.fork();
nextTime._2.addAll(nextFork.join());
return nextTime._2;
}
long minutes = Duration.between(start, end).toMinutes();
long m = minutes / 15;
if (m > 0) {
Tuple2<ZonedDateTime, List<T>> nextTime = doLoop(start, m, z -> z.plusMinutes(15), executeFun);
TimeDivisionTask<T> nextFork = new TimeDivisionTask<>(nextTime._1, end, executeFun);
nextFork.fork();
nextTime._2.addAll(nextFork.join());
return nextTime._2;
}
Tuple2<ZonedDateTime, List<T>> nextTime = doLoop(start, 1, z -> end, executeFun);
return nextTime._2;
}
private Tuple2<ZonedDateTime, List<T>> doLoop(ZonedDateTime start,
long num,
Function<ZonedDateTime, ZonedDateTime> addFun,
BiFunction<ZonedDateTime, ZonedDateTime, List<T>> executeFun) {
List<T> re = new ArrayList<>();
for (int i = 1; i <= num; i++) {
ZonedDateTime _start = start;
ZonedDateTime _end = addFun.apply(_start);
List<T> result = executeFun.apply(_start, _end);
if(CollectionUtils.isNotEmpty(result))
re.addAll(result);
start = _end;
}
return Tuple.of(start, re);
}
public static void main(String[] args) {
ZonedDateTime startDateTime = ZonedDateTime.now(ZoneId.systemDefault()).minusDays(1).withHour(1);
ZonedDateTime endDateTime = ZonedDateTime.now(ZoneId.systemDefault());
BiFunction<ZonedDateTime,ZonedDateTime,List<String>> biFunction = (start,end)-> Lists.newArrayList("从" + start + " 到 " + end + "所有商品");
TimeDivisionTask<String> timeDivisionTask = new TimeDivisionTask<>(startDateTime,endDateTime,biFunction);
List<String> list = ForkJoinPool.commonPool().invoke(timeDivisionTask);
System.out.println(list);
}
}