2016-11-30 54 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

希望這會有所幫助。