前提:某服务1s内只能被一个用户调用10次,满足条件后用户会被限制使用该项服务
1、用户开始使用该服务,先判断用户是否使用过该服务
get user:24
(nil) # 说明该用户还未使用过该服务
2、开始调用,存入用户数据并设立规矩
setex user:24 1 922...797
# 922...807为Redis可存储数据的最大值,作为调用1次的标志,1表示user:24在Redis中的生命周期只有1s
3、第2次调用(直到调用到第10次,仍为以下操作)
incr user:24
4、第11次调用(以Redis最大数值作为判断条件,可不用每次都判断调用次数是否到10了,提高效率)
incr user:24
# 此时会超出Redis可存的最大数值: 922...807,因此会抛异常,程序识别到异常就终止对该用户的服务
5、实现
public class UserService {
private String id;
private int num;
public UserService(String id, int num) {
this.id = id;
this.num = num;
}
public void serviceOperation() {
Jedis jedis = JedisUtil.getJedis(); //通过工具类创建jedis
String value = jedis.get("user_id:" + id);
try {
if (value == null) { //若redis中无用户使用服务信息,则在第一次使用服务时添加信息
jedis.setex("user_id:" + id, 10, Long.MAX_VALUE - num + "");
} else { //若已有信息,则增加累计使用次数
Long val = jedis.incr("user_id:" + id);
business(id,num - (Long.MAX_VALUE - val)); //num-(Long.MAX_VALUE-val)是为了让使用次数看起来合理
}
} catch (JedisDataException e) {
System.out.println("Overflow");
return;
} finally {
jedis.close();
}
}
public void business(String id, Long val) {
System.out.println(id + " Fuck the " + val);
}
}
class MyThread extends Thread {
UserService us = null;
public MyThread(String id, int num) {
us = new UserService(id, num);
}
public void run() {
while (true) {
us.serviceOperation();
try {
Thread.sleep(300L);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
class mainMethod {
public static void main(String[] args) {
//开2个线程,分别对应2种用户
MyThread mt1 = new MyThread("Normal User",10); //通过构造方法传参
MyThread mt2 = new MyThread("VIP User",20);
mt1.start();
mt2.start();
}
}