标签:扫码 code 轮询 线程 countDownLatch 服务器 redisTemplate
基于服务器轮询实现扫码功能
之前的扫码功能是基于轮询和websocket长连接实现的,详情可见:基于轮询或长连接的扫码亮码功能
轮询有个缺点就是扫码端和被扫码端都要一直发起请求查询状态,直到扫码修改了状态才停止请求,这样其实会造成前后端需要大量的网络IO交互。为了避免这种大量的请求,我们可以把这种轮询的请求放到服务器上面去,这里我们修改扫码端的轮询。
实现流程
扫码端扫码之后,后端服务器阻塞主线程,开启一个新的线程轮询读取码的状态,如果码状态修改为已确认,则结束新的线程,释放主线程,返回结果给前端。
具体实现
调用接口之后把状态修改为2,表示已扫描
redisTemplate.opsForValue().set(code, "2", 2, TimeUnit.MINUTES);
用CountDownLatch阻塞主线程,创建一个子线程轮询查询状态
CountDownLatch countDownLatch = new CountDownLatch(1);
CheckThread thread = new CheckThread(countDownLatch, redisTemplate, code);
封装一个FutureTask拿到子线程执行之后返回的结果
FutureTask<String> futureTask = new FutureTask<>(thread);
new Thread(futureTask).start();
阻塞主线程,等待主线程释放后拿到返回结果
try {
countDownLatch.await();
String result = futureTask.get();
//略
} catch (InterruptedException | ExecutionException e) {
e.printStackTrace();
}
子线程的执行过程
private static class CheckThread implements Callable<String> {
int i = 0;
private CountDownLatch latch;
private RedisTemplate<String, String> redisTemplate;
private String code;
public CheckThread(CountDownLatch countDownLatch, RedisTemplate<String, String> redisTemplate, String code) {
this.latch = countDownLatch;
this.redisTemplate = redisTemplate;
this.code = code;
}
@Override
public String call() {
String result = null;
while (i++ < 15) {
String status = redisTemplate.opsForValue().get(code);
//码已过期:null 已确认授权:3 已拒绝:4
if (StringUtils.isBlank(status) || "3".equals(status) || "4".equals(status)) {
result = status;
//countDownLatch计数器减1,前面设置为1,所以这里执行之后为0,子线程执行结束,释放主线程
latch.countDown();
break;
}
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
//用户15秒内未授权扫码
if (i == 16) {
result = "2";
latch.countDown();
}
return result;
}
}
整个过程就是利用CountDownLatch阻塞主线程,等待子线程执行结束释放主线程。
阻塞主线程:countDownLatch.await();
释放主线程:latch.countDown();
标签:扫码,code,轮询,线程,countDownLatch,服务器,redisTemplate 来源: https://blog.csdn.net/m0_54065725/article/details/114648667
本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享; 2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关; 3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关; 4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除; 5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。