package com.example.demo.concurrent.requestmerge;
import com.example.demo.schedule.entity.ISysJobRepository;
import com.example.demo.schedule.entity.SysJobPO;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import javax.annotation.PostConstruct;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.concurrent.*;
/**
* 请求合并:
* 高并发调用这里的服务,针对查询对请求进行合并,
*/
@Service(value="JobServiceImpl2")
public class JobServiceImpl2 implements IJobService {
class Request{
Integer jobId;
CompletableFuture<SysJobPO> result;
}
//存放并发线程调用的参数
private LinkedBlockingQueue<Request> requestQue=new LinkedBlockingQueue<>();
@Autowired
private ISysJobRepository jobRepository;
/**
* 被@PostConstruct修饰的方法会在服务器加载Servlet的时候运行,并且只会被服务器执行一次
* 执行顺序在@Autowired之后
*/
@PostConstruct
public void init() {
System.out.println("合并请求");
ScheduledExecutorService threadPool = Executors.newScheduledThreadPool(1);
//参数1运行的任务,参数2执行时间0立即执行,参数3间隔时间,参数4时间单位
//每10毫秒批量查询一次队列
threadPool.scheduleAtFixedRate(() -> {
ArrayList<Request> requestList = new ArrayList<Request>();
List<Integer> jobIdList = new ArrayList<Integer>();
int size = requestQue.size();
if(size==0)
return;
System.out.println("批量查询大小"+size);
for (int i = 0; i <size; i++) {
Request request = requestQue.poll();
requestList.add(request);
jobIdList.add(request.jobId);
}
//批量查询出所有结果
List<SysJobPO> jobList = getSysJobListByJobIdList(jobIdList);
//讲结果转化为map<k,v> key为jobId value为查询的结果
HashMap<Integer,SysJobPO> map = new HashMap<>();
for (SysJobPO job : jobList) {
map.put(job.getJobId(), job);
}
//讲结果分发给每个线程,即分发给CompletableFuture,根据jobid分发
for (Request request : requestList) {
request.result.complete(map.get(request.jobId));
}
}, 0, 10, TimeUnit.MILLISECONDS);
}
@Override
public SysJobPO selectByPrimaryKey(Integer jobId) {
Request request=new Request();
CompletableFuture<SysJobPO> futureResult = new CompletableFuture<>();
request.jobId=jobId;
request.result=futureResult;
requestQue.add(request);
SysJobPO job=null;
try {
//阻塞至futureResult.complete()方法
job = futureResult.get();
} catch (InterruptedException | ExecutionException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return job;
}
@Override
public List<SysJobPO> getSysJobListByJobIdList(List<Integer> jobIds) {
return jobRepository.findByJobIdIn(jobIds);
}
}