使用Java一次最大异步调用数

时间:2018-09-05 07:25:21

标签: java asynchronous

我有一个异步方法,需要多次调用。我一次只能打这么多电话有什么限制吗?如果是,限制的最佳方法是什么。是thread.sleep很好还是还有其他方法吗?

我可能需要多次调用该方法5万次。在不同的系统中,其行为不受任何限制。对于一个系统,它已成功完成,而在另一个系统之间,它已停止。期待它是因为异步调用过多

更新 示例代码

 @Async
        public void download(){
    //download file from server
    }
    public void callDownload(){
    for( int i =0; i <100000; i++)
      download();
    }

谢谢!

2 个答案:

答案 0 :(得分:0)

异步调用分为两部分。客户端和服务器(可能是)。

  1. 异步调用的最大数量(实际上并行执行)将取决于客户端计算机上的线程资源。您可以根据需要多次调用该方法,但是实际的执行将通过编程语言调用堆栈或该计算机的操作系统来计划。因此,答案是-这取决于您拥有的资源类型。

  2. 这还取决于您进行的呼叫类型-是服务器/网络呼叫?您是在向数据库,队列等发出请求吗?这些系统可能会对并行处理的请求数量有自己的限制,而其余的呼叫阻塞操作。这取决于。

因此,从语言角度看,您可以随意拨打任意数量的电话,直到达到硬件限制为止。

根据可用线程/处理器的数量合理地限制异步并行调用始终是一件好事。

答案 1 :(得分:0)

好的,所以我们实际上在谈论的是使用Spring @async机制实现的异步调用。

根据https://www.baeldung.com/spring-async

  

简单地说-用@Async注释bean的方法将使其在单独的线程中执行 ;也就是说,调用者将不会等待被调用方法的完成。

  

默认情况下,Spring使用SimpleAsyncTaskExecutor实际异步运行这些方法。

SimpleAsyncTaskExecutor的{​​{3}}中,我们看到:

  

TaskExecutor实现可为每个任务启动一个新线程,以异步方式执行。

     

通过“ concurrencyLimit” bean属性支持限制并发线程。默认情况下,并发线程数是无限的。

     

注意:此实现不重用线程!请考虑使用线程池TaskExecutor实现,特别是对于执行大量短期任务。

因此,我们可以得出以下结论(除非您做了一些未提及的额外调整):

  1. 每个异步调用都使用一个单独的线程。
  2. 没有线程池可以回收线程。
  3. 该机制不限制创建的线程数。

创建线程很昂贵,并且每个线程都消耗大量内存。因此,我希望发生的事情是您通过过多的线程使JVM重载,并且它正在磨碎..至.. a ........停止。 (要么是由于GC死机,要么是由于尝试同时进行太多下载而导致的虚拟内存崩溃,要么是网络拥塞。)

基本上,这种幼稚的方法无法扩展。更好的主意是将ExecutorService与有限线程池一起使用,并将下载请求作为任务提交。执行程序服务将使任务排队并将其提交到其工作线程池中。您应该调整线程池的大小,以免它淹没您的本地内存/计算,网络连接...以及您正在通过并行下载进行锤击的远程服务器。

远程服务器也可能限制您的下载...因为您的大规模并行下载看起来像 DOS攻击。