高并发请求合并如何自己实现呢

对外提供查询job的接口,这个接口并发查询特别大,如何实现请求合并呢

当然了,请求合并针对并发百万的情况使用,不要滥用.....................

首先我们看到请求参数为jobId,返回结果为job

那我们就要针对它建一个类来操作这些参数,并发其实就是多线程,我们用Request类来存放每个线程的参数

class Request{
		Integer jobId;
		CompletableFuture<Job> result;
	}

其次,在服务类设置一个私有属性,Service都是单例的要记住,这里面存放每个线程参数的对象,其实就是把并发的请求存放在队列里

//存放并发线程调用的参数
	private  LinkedBlockingQueue<Request> requestQue=new LinkedBlockingQueue<>();

在服务类建立定时任务,定时处理队列里面的请求

/**
	 * 被@PostConstruct修饰的方法会在服务器加载Servlet的时候运行,并且只会被服务器执行一次
	 * 执行顺序在@Autowired之后
	 * @param jobId
	 */
	@PostConstruct
	public void init() {
		System.out.println("合并请求");
		ScheduledExecutorService threadPool = Executors.newScheduledThreadPool(1);
		//参数1运行的任务,参数2执行时间0立即执行,参数3间隔时间,参数4时间单位
		//每10毫秒批量查询一次队列
		threadPool.scheduleAtFixedRate(new Runnable() {
			@Override
			public void run() {
				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<Job> jobList = jobMapper.selectByPrimaryKeyBath(jobIdList);
				//讲结果转化为map<k,v>  key为jobId value为查询的结果
				HashMap<Integer,Job> map = new HashMap<Integer,Job>();
				for (Job 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 Job selectByPrimaryKey(Integer jobId) {
		Request request=new Request();
		CompletableFuture<Job> futureResult = new CompletableFuture<Job>();
		request.jobId=jobId;
		request.result=futureResult;
		requestQue.add(request);
		Job job=null;
		try {
			//阻塞至futureResult.complete()方法
			 job = futureResult.get();
		} catch (InterruptedException | ExecutionException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		return job;
	}

---------------------------------------------------------------------------------------------------------------------------------------------------------------------

完整代码

@Service(value="JobServiceImpl2")
/**
 * 高并发调用这里的服务,针对查询对请求进行合并,
 *
 */
public class JobServiceImpl2 implements IJobService {
	class Request{
		Integer jobId;
		CompletableFuture<Job> result;
	}
	//存放并发线程调用的参数
	private  LinkedBlockingQueue<Request> requestQue=new LinkedBlockingQueue<>();
	@Autowired
	private JobMapper jobMapper;
	
	/**
	 * 被@PostConstruct修饰的方法会在服务器加载Servlet的时候运行,并且只会被服务器执行一次
	 * 执行顺序在@Autowired之后
	 * @param jobId
	 */
	@PostConstruct
	public void init() {
		System.out.println("合并请求");
		ScheduledExecutorService threadPool = Executors.newScheduledThreadPool(1);
		//参数1运行的任务,参数2执行时间0立即执行,参数3间隔时间,参数4时间单位
		//每10毫秒批量查询一次队列
		threadPool.scheduleAtFixedRate(new Runnable() {
			@Override
			public void run() {
				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<Job> jobList = jobMapper.selectByPrimaryKeyBath(jobIdList);
				//讲结果转化为map<k,v>  key为jobId value为查询的结果
				HashMap<Integer,Job> map = new HashMap<Integer,Job>();
				for (Job 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 Job selectByPrimaryKey(Integer jobId) {
		Request request=new Request();
		CompletableFuture<Job> futureResult = new CompletableFuture<Job>();
		request.jobId=jobId;
		request.result=futureResult;
		requestQue.add(request);
		Job job=null;
		try {
			//阻塞至futureResult.complete()方法
			 job = futureResult.get();
		} catch (InterruptedException | ExecutionException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		return job;
	}
}

并发测试

@SpringBootTest(classes=SpringbootStartApplication.class)
@WebAppConfiguration
@RunWith(SpringRunner.class)
public class SpringTest {
	@Resource(name="JobServiceImpl2")
	private IJobService jobService;
	@Test
	public void test1(){
		Job job = jobService.selectByPrimaryKey(2);
		System.out.println(job);
	}
	
	@Test
	public void bingfa() throws InterruptedException, IOException{
		CountDownLatch countDownLatch=new CountDownLatch(1000);
		for (int i = 0; i <1000; i++) {
			final int j=i;
			new java.lang.Thread(new Runnable() {
				public void run() {
					try {
						countDownLatch.await();
						Job job = jobService.selectByPrimaryKey(j);
					} catch (InterruptedException e) {
						// TODO Auto-generated catch block
						e.printStackTrace();
					}
				}
			}
			).start();
			countDownLatch.countDown();
		}
		System.in.read();
	}
}

 

  • 0
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值