代码实现
package com.zzh.circle;
import lombok.extern.slf4j.Slf4j;
import java.time.LocalDateTime;
import java.util.Map;
import java.util.Random;
import java.util.Set;
import java.util.TreeSet;
import java.util.concurrent.*;
import java.util.concurrent.atomic.AtomicInteger;
/**
* @author zzh
* @date 2019/5/18
*/
@Slf4j
public class UserLoginOverTimeHandler {
//环形队列 30s超时就创建30个slot,精确到秒,60s则是60个
static Set<Integer>[] slots = new Set[30];
//记录uid落在了哪个slot中,key是uid,value是slot的下标
static Map<Integer, Integer> slotMapper = new ConcurrentHashMap<>();
//当前指向了环形队列的哪个slot
static AtomicInteger currentIndex = new AtomicInteger(0);
//上一个index
static AtomicInteger previousIndex = new AtomicInteger(slots.length - 1);
static {
//初始化slots
for (int i = 0; i < slots.length; i++) {
slots[i] = new TreeSet();
}
//定时移动环形队列,即改变环形队列currentIndex的指向
ScheduledExecutorService scheduledExecutorService = Executors.newScheduledThreadPool(1);
//定时移动环形队列
scheduledExecutorService.scheduleAtFixedRate(() -> {
//删除当前slot中的set
log.info("删除slot---->{},超时用户--->{}", currentIndex.get(), slots[currentIndex.get()]);
slots[currentIndex.get()].clear();
//到达终点
if (currentIndex.get() == slots.length - 1) {
//移动到起点
currentIndex.set(0);
//前进一格
previousIndex.getAndIncrement();
} else if (currentIndex.get() == 0) {
//前进一格
currentIndex.getAndIncrement();
//移动到起点
previousIndex.set(0);
} else {
//前进一格
currentIndex.getAndIncrement();
previousIndex.getAndIncrement();
}
}, 0, 1, TimeUnit.SECONDS);
}
//处理请求
public void handRequest(Integer uid) {
log.info("当前时间{},收到来自uid--->{}的请求", LocalDateTime.now(), uid);
//查找是否有落在slot中
boolean isExist = slotMapper.containsKey(uid);
//存在则删除,放入上一个slot中
if (isExist) {
Integer slotIndex = slotMapper.get(uid);
slotMapper.remove(uid);
//获取到slot对应的set
Set<Integer> set = slots[slotIndex];
for (Integer setUid : set) {
if (setUid.equals(uid)) {
set.remove(setUid);
log.info("slot index--->{}, set 中删除了uid---->{}", slotIndex, uid);
break;
}
}
}
//记录新slot下标
slotMapper.put(uid, previousIndex.get());
//放入新slot
Set<Integer> uidSet = slots[previousIndex.get()];
uidSet.add(uid);
log.info("slot set 中放入了新用户,slotindex--->{},uid--->{}", previousIndex.get(), uid);
}
public static void main(String[] args) {
UserLoginOverTimeHandler userLoginOverTimeHandler = new UserLoginOverTimeHandler();
ExecutorService executorService = Executors.newFixedThreadPool(3);
int[] uids = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
for (int i = 0; i < 13; i++) {
executorService.execute(() -> {
Random random = new Random();
try {
int sleepTime = random.nextInt(35);
int uidIndex = random.nextInt(10);
Thread.sleep(sleepTime * 1000);
userLoginOverTimeHandler.handRequest(uids[uidIndex]);
} catch (InterruptedException e) {
e.printStackTrace();
}
});
}
//任务全部执行完毕后关闭
executorService.shutdown();
}
}
运行结果