static class Tuple implements Comparable<Tuple> {
private long uid;
private long score;
public long getUid() {
return uid;
}
public Tuple setUid(long uid) {
this.uid = uid;
return this;
}
public long getScore() {
return score;
}
public Tuple setScore(long score) {
this.score = score;
return this;
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
Tuple tuple = (Tuple) o;
return Objects.equals(uid, tuple.uid);
}
@Override
public int hashCode() {
return Objects.hash(uid);
}
@Override
public int compareTo(Tuple tuple) {
return compare(this, tuple);
}
public static int compare(Tuple x, Tuple y) {
return Comparator.nullsFirst(Comparator.comparing(Tuple::getScore).thenComparing(Tuple::getUid)).compare(x, y);
}
}
public static Set<Tuple> concurrentSkipListSet = new ConcurrentSkipListSet<>();
public static ConcurrentSkipListMap<Long, Tuple> concurrentSkipListMap = new ConcurrentSkipListMap<>();
public static void main(String[] args) throws Exception {
BiFunction<Long, Long, Long> function = (temUid, temScore) -> {
//累加用户积分且返回累加后的积分
return concurrentSkipListMap.compute(temUid, (temKey, oldValue) -> {
Tuple tuple = Optional.ofNullable(oldValue).map(temTuple -> {
//移除跳表中的旧对象
concurrentSkipListSet.remove(temTuple);
//累加
return temTuple.setScore(temTuple.getScore() + temScore);
}).orElseGet(() -> new Tuple().setUid(temUid).setScore(temScore));
//添加到跳表
concurrentSkipListSet.add(tuple);
//返回计算结果
return tuple;
}).getScore();
};
//两个数据集合操作不是原子性的,所以只能单线程或者加同步锁实现 这里选择和redis一样的处理方案-单线程
ExecutorService executorService = Executors.newWorkStealingPool(1);
List<CompletableFuture<Void>> completableFutures = IntStream.rangeClosed(1, 9876).mapToObj(value -> CompletableFuture.runAsync(() -> function.apply(Long.valueOf(value % 10), Long.valueOf(1)), executorService)).collect(Collectors.toList());
completableFutures.stream().map(CompletableFuture::join).collect(Collectors.toList());
System.out.println(JSONObject.toJSONString(concurrentSkipListSet));
}
执行结果:
[{
"score":987,
"uid":0
},{
"score":987,
"uid":7
},{
"score":987,
"uid":8
},{
"score":987,
"uid":9
},{
"score":988,
"uid":1
},{
"score":988,
"uid":2
},{
"score":988,
"uid":3
},{
"score":988,
"uid":4
},{
"score":988,
"uid":5
},{
"score":988,
"uid":6
}]