2013-01-11 22 views
4

如何控制和平衡我的應用程序正在執行的線程數量,如何限制它們的數量以避免應用程序阻塞,因爲已達到線程限制?如何以編程方式控制和平衡iOS應用程序正在執行的多個線程?

在這裏,所以我看到以下可能的答案:「主併發隊列(dispatch_get_global_queue)自動管理線程的數量」,我不喜歡,原因如下:

考慮以下模式(在我真正的應用程序有兩個更簡單,更復雜的例子):

dispatch_queue_t defaultBackgroundQueue() { 
    return dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0); 
} 

dispatch_queue_t databaseQueue() { 
    dispatch_queue_create("Database private queue", 0); 
} 

dispatch_async(defaultBackgroundQueue(), ^{ 
    [AFNetworkingAsynchronousRequestWithCompletionHandler:^(data){ 
     dispatch_async(databaseQueue(), ^{ 
      // data is about 100-200 elements to parse 
      for (el in data) { 

      } 

      maybe more AFNetworking requests and/or processing in other queues or 

      dispatch_async(dispatch_get_main_queue(), ^{ 
       // At last! We can do something on UI. 
      }); 
     }); 
    }]; 
}); 

這種設計非常往往導致這種情況的時候:

  1. 的應用由於線程數量限制已達到(類似於> 64)而被鎖定(類似於> 64)
  2. 速度較慢,因此窄隊列可能會被大量未決作業淹沒。
  3. 第二個也可以產生取消問題 - 如果我們有100個作業已經在串行隊列中等待執行,我們不能立即取消它們。

顯而易見的解決方案是用dispatch_sync替換敏感的dispatch_async方法,但它絕對是我不喜歡的。

這種情況下推薦的方法是什麼?

我希望一個比「僅使用NSOperationQueue - 它可以限制併發操作數量」更爲智能的答案確實存在(類似主題:Number of threads with NSOperationQueueDefaultMaxConcurrentOperationCount)。

更新1:唯一像樣的模式是看到:是將所有的塊的dispatch_async替換爲併發隊列,在NSOperationQueue基於併發隊列中運行這些塊的NSOperations中包含最大操作數限制(在我的情況下,最大操作限制在AFNetworking在其中運行其所有操作的基於NSOperationQueue的隊列中)。

+0

你是什麼意思「該應用程序被鎖定」?您將始終有一些線程正在執行,並且只要某些線程正在執行,您的應用程序就會取得進展。 –

+0

你是什麼意思,「不知所措」?如果您提交作業的速度比CPU能夠執行的速度快,那麼無論它們有多寬,隊列都會被積壓。 –

+0

隨着你使用的方法(或NSOperation,就此而言),顯式線程的創建和觸發超出了範圍。我不一定同意這個問題和你想的一樣 - 但是,在回答這個問題時,你可以明確地控制創建的線程數的唯一方法是手動創建它們,例如使用NSThread。 – isaac

回答

7

您正在啓動太多的網絡請求。 AFAIK它沒有記錄在任何地方,但你可以同時運行多達6個網絡連接(考慮到RFC 2616 8.1.4第6段,這是一個明智的數字)。之後,您會鎖定,並且GCD會補償創建更多線程,順便提一下,請撥打have a stack space of 512KB each。所以是的,爲此使用NSOperation。我用它排隊網絡請求,當再次請求同一個對象時增加優先級,如果用戶離開,暫停並序列化到磁盤。我還以字節/時間監視網絡請求的速度並更改併發操作的數量。

+0

你是一個傳奇人物,我喜歡這個解釋非常有幫助。 – Supertecnoboff

1

雖然我沒有從您的示例中看到您正在創建「太多」後臺線程的位置,但我會試着回答如何控制每個隊列的確切線程數問題。蘋果documentation說:

併發隊列(也稱爲類型的全局調度隊列)執行一個或多個任務同步,但任務在它們被添加到隊列的順序仍然啓動。當前正在執行的任務在由調度隊列管理的不同線程上運行。在任何給定點執行的任務的確切數量是可變的,並取決於系統條件。

雖然您現在可以(自iOS5開始)手動創建併發隊列,但無法控制此類隊列將同時運行多少個作業。操作系統將自動平衡負載。如果出於某種原因,你不希望出現這種情況,例如,您可以手動創建一組ň串行隊列,並隨機分派新的工作機會,以你的ň隊列之一:

NSArray *queues = @[dispatch_queue_create("com.myapp.queue1", 0),dispatch_queue_create("com.myapp.queue2", 0),dispatch_queue_create("com.myapp.queue3", 0)]; 
NSUInteger randQueue = arc4random() % [queues count]; 
dispatch_async([queues objectAtIndex:randQueue], ^{ 
    NSLog(@"Do something"); 
}); 
randQueue = arc4random() % [queues count]; 
dispatch_async([queues objectAtIndex:randQueue], ^{ 
    NSLog(@"Do something else"); 
}); 

我我決不支持這種設計 - 我認爲併發隊列在平衡系統資源方面非常出色。但是既然你問了,我認爲這是一個可行的方法。

相關問題