大量创建线程从来都不是一个好主意(如果您创建太多线程,可能会耗尽内存)。通常情况下,Jersey每个请求需要创建一条线程。无论是使用async()(在这种情况下,Jersey为我创建线程,我已经在调试器中进行了研究),还是不使用(在这种情况下,我显然必须自己创建线程),这似乎都是适用的。所以这里有一个具体的情况表明这样做还不够好:我正在以每秒多达500个请求的速度向远程服务器发送HTTP POST请求。但是由于响应可能要花费一些时间才能到达(我计算最多需要30秒),因此总线程数很容易达到几千个(此时,JVM进程通常会崩溃)。此外,创建如此多的线程就是疯狂的。对于可用的处理器/网络/操作系统资源来处理这个负载实际上应该很容易。
所以我想做的就是仅仅发出请求,并且在HTTP响应到达时由操作系统通知我。简单地使用target.request(...).async()并不起作用(因为在这种情况下,Jersey只会生成它自己的线程)。此外,限制线程数量通过new ClientConfig().property(ClientProperties.ASYNC_THREADPOOL_SIZE, 10)根本没有帮助,因为这意味着最多只能同时发送10个请求,这显然不是我想要的(它只会堆积队列)。我尝试使用new ClientConfig().connectorProvider(new GrizzlyConnectorProvider())来获取NIO支持,但根本没有看到任何行为上的差异。那么有没有一种方法可以发出请求而不必为每个请求创建一个额外的线程呢?
所以我想做的就是仅仅发出请求,并且在HTTP响应到达时由操作系统通知我。简单地使用target.request(...).async()并不起作用(因为在这种情况下,Jersey只会生成它自己的线程)。此外,限制线程数量通过new ClientConfig().property(ClientProperties.ASYNC_THREADPOOL_SIZE, 10)根本没有帮助,因为这意味着最多只能同时发送10个请求,这显然不是我想要的(它只会堆积队列)。我尝试使用new ClientConfig().connectorProvider(new GrizzlyConnectorProvider())来获取NIO支持,但根本没有看到任何行为上的差异。那么有没有一种方法可以发出请求而不必为每个请求创建一个额外的线程呢?
sysctl kern.num_taskthreads
显示kern.num_taskthreads: 2048
- 而且似乎Oracle JVM实际上使用内核线程(有趣)。 - Chris Lercher