2016-11-30 49 views
0

我可能在这里问一个设计模式问题。如何处理ThreadPool达到服务器连接限制

在Android上,我使用线程池来打开8个线程来下载一些文件。

try { 
     ExecutorService pool = Executors.newFixedThreadPool(8); 
     for (int i = 0; i < someList.size(); i++) { 
      pool.submit(new DownloadJsonTask(someList.get(i), context)); 
     } 
     pool.shutdown(); 
     pool.awaitTermination(Long.MAX_VALUE, TimeUnit.MILLISECONDS); 
    } catch (Exception e) { 
    } 

我发现,如果我使用一个线程一个接一个来下载的话,我很难得到下载失败,但如果我用8个线程,然后我有时会收到下载失败。我不是一个服务器/网络人员,所以我不知道详细信息,但我猜测服务器正在试图连接多个连接的设备(或一个IP地址)的限制。

如果这是原因,那么我该如何设计代码来解决这个问题?我已经实施尝试下载3次失败之前。它似乎固定它“现在”。但是,我知道我的代码不健壮,可能会失败。

我想,我不会是第一个面临这个问题的人。我想知道围绕此问题的强大解决方案。

解决方案我能想到的:
- 尝试失败
之前下载至少3倍 - 一旦失败,再尝试睡一个随机的时间量。因此,失败的线程不会同时唤醒并再次失败。
- 如果服务器抛出某种独特的消息,例如服务器繁忙,则重新尝试无限(?)(大量)次。

我还没有实现上述可能的解决方案。我想首先了解这个通用/最佳解决方案,并花时间实施它。

任何想法?

回答

2

这个问题是基于意见的。我分享我的看法。

理想情况下,如果您可以检查服务器日志,并发现它是应该修复的服务器端的东西,那么您应该首先执行该操作。

除此之外,即使客户端和服务器能够多线程并处理并发,也总会出现网络故障。也就是说,你应该在你的客户端有一个重试机制。

关于重试策略

  1. 保持重试配置,而不是将其固定到3.一些设计要点(你可以想出正确的号码上分析和测试的尝试)
  2. 代替睡了一段随机时间,试试exponential backoff
  3. 除了重试无限次,我们可以将消息标记给用户,以便在指数退避后重试自己。 (类似于“正在加载的网站,请稍后再试一次”)。
  4. 查看为您执行重试的库。类似this
  5. 网络带宽也可能是下载失败的原因。您可以监控网络速度和类型(WiFi,LTE,3G)等,并决定是否下载或安排日后安排。

另一篇文章here

希望这会有所帮助。