Java:进行异步调用会增加线程数吗?

Java:进行异步调用会增加线程数吗?,java,multithreading,asynchronous,Java,Multithreading,Asynchronous,假设我有一个web应用程序,每个请求都会产生一个新线程。数百个请求进入,在web服务器代码的某个地方,我们对多个服务进行同步调用,然后阻塞并等待。由于同步调用造成了瓶颈,这种方法会增加线程的数量 假设,如果我们将这些调用切换到异步请求,我们就可以摆脱瓶颈,因为线程可以继续,回调将处理任何需要发生的事情 据我所知,在Java中,为了进行异步调用,我们生成了一个新线程,该线程进行网络调用并包含回调(我不会实现这个,我假设一些Java http库就是这样工作的) 我的问题是,这是如何解决多线程的问题的

假设我有一个web应用程序,每个请求都会产生一个新线程。数百个请求进入,在web服务器代码的某个地方,我们对多个服务进行同步调用,然后阻塞并等待。由于同步调用造成了瓶颈,这种方法会增加线程的数量

假设,如果我们将这些调用切换到异步请求,我们就可以摆脱瓶颈,因为线程可以继续,回调将处理任何需要发生的事情

据我所知,在Java中,为了进行异步调用,我们生成了一个新线程,该线程进行网络调用并包含回调(我不会实现这个,我假设一些Java http库就是这样工作的)

我的问题是,这是如何解决多线程的问题的?异步请求最终会创建更多线程(每个请求一个线程),然后进入睡眠状态,直到返回某个线程,这不是会创建许多睡眠线程吗


我试图解决的问题是,在某个时候,当线程太多时,JVM就会爆炸。

没有线程太多的问题,服务器总是有一个线程池。它们将线程池中的一个线程分配给每个请求,如果线程不可用,服务器只会让请求套接字在ServerSocket的队列中等待

Servlet 3中的异步请求处理试图解决的问题是,由于请求处理线程阻塞,资源利用率降低

因此,如果有长时间运行的请求只是等待I/O,它们将被搁置,直到从I/O通道接收到响应,并且该线程被分配给套接字队列中等待的另一个请求


这为我们提供了更好的资源(主要是CPU)利用率,并通过put提供了更多的资源,因为每秒有更多的请求(持续时间较短的请求)被服务。

特别是在web服务/servlet环境中:

在最简单的配置中,公共web服务器(Jetty、Tomcat)配置有固定数量的线程,或线程数量范围。如果到达的请求多于线程,那么这些请求将堆积在内核连接队列中。线程接受连接并完成所有工作。发送响应时,线程可用于另一个连接。添加您自己的线程池或执行器服务不会有帮助

在更复杂的配置中,web容器在一个线程池上接受连接,然后在另一个线程池上分派工作,其间有一个队列。然后,他们不再阻塞connect上的客户端,或者让它们无法连接,而是等待

在异步Servlet处理中,例如JAX-RS
@suspended AsyncResponse
对象,您可以自己控制该对象的细节。servlet使用包含连接的数据结构调用您。您的代码可以将该对象放入某个队列(可能只是Executor服务中内置的队列),然后返回。释放web服务器线程以接受另一个容器。您的线程(可能来自Executor服务)在队列中工作,处理请求并发送响应


你永远不会创建无限数量的线程。

异步意味着请求由另一个线程处理。它不必是专用线程,更不用说新线程了

例如,考虑:

target()。路径(“http://example.com/resource/")
.request().async().get(新调用回调(){
@凌驾
公共无效已完成(来自后端服务器的字符串数据){
响应(来自后端服务器的数据);
}
@凌驾
公共作废失败(可丢弃可丢弃){
响应器(可丢弃);
}
});
这里,调用回调在JAX-RS实现提供的线程中执行,该线程等待对任何挂起的后端请求的响应,然后使用适当的调用回调处理该响应。由于单个线程可以等待任意数量的挂起后端请求,因此需要更少的线程


这就是说,同步处理通常更容易实现,虽然它的可扩展性不如异步处理,但它的可扩展性足以满足许多应用程序的需要。也就是说,除非您有数千个并发请求,否则普通的旧同步处理模型就可以了。

是发生了这种情况还是您在谈论一些理论问题?没有必要在每次收到请求时生成新线程。通常,这是由线程池解决方案处理的。我的问题是关于服务在请求到达后执行的阻塞/非阻塞调用。这不会产生更多的线程吗?非阻塞呼叫在幕后是如何工作的?您必须更加具体。Java中几乎没有API“创建更多线程”。
target().path("http://example.com/resource/")
    .request().async().get(new InvocationCallback<String>() {
        @Override
        public void completed(String dataFromBackendServer) {
            respondWith(dataFromBackendServer);
        }

        @Override
        public void failed(Throwable throwable) {
            respondWithError(throwable);
        }
    });