还是 Futrue.get() 堵塞当前线程的问题

2019-05-29 14:02:12 +08:00
 aoscici2000

@RestController
public class ThreadController {

	@Resource(name = "taskExecutor")
	private ThreadPoolTaskExecutor executor;

	@GetMapping("/check")
	public Map<String, Object> check() throws Exception{

		Map<String, Object> map = new HashMap<>();

		Future<Integer> pa = executor.submit(new CheckPrice(a));
		Future<Integer> pb = executor.submit(new CheckPrice(b));
		Future<Integer> pc = executor.submit(new CheckPrice(c));

		Integer[] priceList = { pa.get(), pb.get(), pc.get() };
		map.put("最小价格", Collections.min(Arrays.asList(priceList)));

		return map;
	}
}

假设每个 CheckPrice 需要 2 秒耗时, 有多人同时访问"/check"的时候, 怎样才能让每个人都只是等 2 秒, 而不用排队一个个处理?

貌似只要是需要等待 Future.get 结果的, controller 都是堵住的, CompletableFuture 也看了一个早上, 好像也会堵 controller, 或者返回空值的...

1725 次点击
所在节点    Java
8 条回复
phx13ye
2019-05-29 14:05:05 +08:00
你咋测的,executor 里的线程够不够啊,如果你 executor 有 6 个线程,同时两人访问,这两个人就是等两秒啊,不是四秒啊
aoscici2000
2019-05-29 14:17:11 +08:00
@phx13ye 开 8 线测 2 人, 结果有一个得等 4 秒...
sujin190
2019-05-29 15:01:52 +08:00
纯 cpu 计算但是双核 cpu ?
firefffffffffly
2019-05-29 15:06:27 +08:00
1. 你这里涉及到两个多线程,一个是 check()请求函数发生的线程池 executorA,一个是你自己定义执行 CheckPrice 的 executorB
2. 你的问题和 executorB 没有太大关系,它的线程数只影响 Future.get()的耗时,最少 2s, 任何类型的 Future.get()一样会阻塞至少 2s。
3. 由 2 可知你每次 check()函数被调用最少会阻塞 2s,这时 executorA 如果是单线程模型,两个请求一定会有一个等待 4s。
4. executorA 线程数取决于 servlet 容器的配置

解决方案
1. 修改 servlet 的配置,增加 executorA 线程数,治标不治本,优点是简单
2. check()修改为异步非阻塞返回模型,参考你之前帖子里 9 楼回复的 CompletableFuture + DeferredResult 方案
Jrue0011
2019-05-31 16:28:51 +08:00
ThreadPoolTaskExecutor 内部其实就是创建了一个 ThreadPoolExecutor 吧,需要指定 queueCapacity,默认是 Integer.MAX_VALUE,你可以指定为 1 或者 0 试试看...不然队列不满的话是不会去创建新线程执行任务的
Jrue0011
2019-05-31 16:34:46 +08:00
@Jrue0011 仔细看了下,ThreadPoolTaskExecutor 默认的 corePoolSize=1,线程池的逻辑好像是这样的,一开始有 corePoolSize 的线程,如果这些线程都被使用则新任务进入队列,如果队列满了则创建新线程直到 maxPoolSize,所以也可能是线程池的 corePoolSize 是默认的 1。。。
Jrue0011
2019-05-31 17:37:00 +08:00
刚刚自己写了个测试下,第二个请求响应慢的问题可能是出在浏览器(chrome,其他浏览器没测试)上。。。用 postman 同时发两个请求,响应的时间就基本一样了
aoscici2000
2019-05-31 23:00:03 +08:00
@Jrue0011 晕死了, chrome 好像真有点大坑, 之前一直觉得刷新两个窗口来试试就行...结果浏览器一直有毛病, 用脚本测一下才正常...

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/568739

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX