SDWebimage相關知識點1-- NSOperation

GCD      
GCD是最經常使用的管理並行代碼和執行異步操做的Unix系統層的API。GCD構造和管理隊列中的任務。
 
隊列是按先進先出(FIFO)管理對象的數據結構。隊列相似電影院的售票窗口,票的銷售是誰先到誰先服務。在等待線前面的人先去買他們的門票,在其他的後抵達的人以前。隊列在計算機科學中是類似的,由於第一個添加到隊列的對象也是第一個從隊列中刪除的對象。
 
 
操做隊列  NSOperationQueue
 
GCD是一個底層的C的API,它使開發人員可以並行地執行任務。操做隊列,另外一方面,是高度抽象的隊列模型,是創建在GCD之上的。這意味着你能夠並行執行任務就像GCD同樣,但以面向對象的方式。簡而言之,隊列操做讓編程更加簡單。
 
不一樣於GCD,它們不按先進先出的順序。下面是操做隊列和調度隊列的不一樣點:
 
1.不遵循先進先出:在操做隊列中,你能夠設置一個操做的執行優先級,你能夠添加操做之間的依賴關係,這意味着你能夠定義一些操做完成後纔會執行其餘操做。這就是爲何它們不遵循先進先出。
2.默認狀況下,它們同時操做:然而你不能把它的類型改變成串行隊列。經過使用操做之間的依賴關係,在操做隊列還存在一個工做區來依次執行任務。
3.操做隊列是類NSOperationQueue的實例,其任務封裝在NSOperation的實例裏。
 
 
NSOperation
 
是蘋果提供的一套多線程解決方案,實際上NSOperation是基於GCD 更高一層的封裝,可是比GCD 更簡單易用、代碼可讀性更高。 
 
須要配合NSOperationQueue 來實現多線程。 默認狀況下,單獨使用NSOperation時系統執行同步操做,並無開闢新線程的能力,只有和配合NSOperationQueue 才能實現異步執行。 
 
由於NSOperation是基於GCD的,那麼使用起來也和GCD差很少,其中,NSOperation至關於GCD中的任務,而NSOperationQueue則至關於GCD中的隊列。NSOperation實現多線程的使用步驟分爲三步:
  1. 建立任務:先將須要執行的操做封裝到一個NSOperation對象中。
  2. 建立隊列:建立NSOperationQueue對象。
  3. 將任務加入到隊列中:而後將NSOperation對象添加到NSOperationQueue中。
以後呢,系統就會自動將NSOperationQueue中的NSOperation取出來,在新線程中執行操做。
 
NSOperation是一個抽象類,它不能直接使用,因此你必須使用NSOperation子類。在iOS SDK裏,咱們提供兩個NSOperation的具體子類。這些類能夠直接使用,但你也能夠繼承NSOperation來建立本身的類來執行操做。咱們能夠直接使用的兩個類:
 
 
1.NSBlockOperation——使用這個類來用一個或多個block初始化操做。操做自己能夠包含多個塊。當全部block被執行操做將被視爲完成。
 
2.NSInvocationOperation——使用這個類來初始化一個操做,它包括指定對象的調用selector。
 
或者定義繼承自NSOperation的子類,經過實現內部相應的方法來封裝任務。
 
NSOperationQueue
 
和GCD中的併發隊列、串行隊列不一樣的是,NSOperationQueue 一共有兩種隊列:主隊列、其餘隊列。 
其餘隊列中包含了串行、併發功能。 
 
NSOperationQueue *queue = [NSOperationQueue mainQueue];//主隊列
NSOperationQueue *queue = [[NSOperationQueue alloc] init];//其餘隊列
 
將任務加入到隊列中
1.先建立任務,再將建立好的任務加入到建立好的隊列中去
- (void)addOperation:(NSOperation *)op;
 
2.無需建立任務,在block中執行任務,直接將任務block加入到隊列中
(void)addOperationWithBlock:(void (^)(void))block;
 
 
控制串行執行和併發執行的關鍵
 
最大併發數:maxConcurrentOperationCount
默認狀況下是-1,表示不進行限制,默認爲併發執行。
當爲1時,進行串行執行。
當>1時,進行併發執行。
 
 
操做依賴
NSOperation和NSOperationQueue最吸引人的地方是它能添加操做之間的依賴關係。好比說有A、B兩個操做,其中A執行完操做,B才能執行操做,那麼就須要讓B依賴於A。
 
- (void)addDependency
 
一些其餘的方法:
  • - (void)cancel; NSOperation提供的方法,可取消單個操做
 
 
  • - (void)cancelAllOperations; NSOperationQueue提供的方法,能夠取消隊列的全部操做
 
  • - (void)setSuspended:(BOOL)b; 可設置任務的暫停和恢復,YES表明暫停隊列,NO表明恢復隊列
 
  • - (BOOL)isSuspended; 判斷暫停狀態
 
 
注意:
這裏的暫停和取消並不表明能夠將當前的操做當即取消,而是噹噹前的操做執行完畢以後再也不執行新的操做
 
  • 暫停和取消的區別就在於:暫停操做以後還能夠恢復操做,繼續向下執行;而取消操做以後,全部的操做就清空了,沒法再接着執行剩下的操做。
 
自定義子類:
 
使用main方法,不須要管理一些狀態屬性(如isExecuting 和 isFinished ),當main 方法返回的時候,這個operation 就結束了。 這種方式使用起來很是簡單,main方法執行完就認爲operation 結束了。因此通常能夠用來執行同步任務。
 
若是你但願擁有更多的控制權,或者想在一個操做中能夠執行異步任務,那麼就重寫start 方法。 
在這種狀況下,必須手動管理操做的狀態,只有當發送isFinished 的kvo 消息時,才認爲是operation 結束。
 

 
 
 
因此NSOperation的優點是什麼?
 
1.首先,它們經過NSOperation類裏的方法addDependency(op:NSOperation)支持依賴。當你須要開始一個依賴於其它操做執行的操做,你會須要NSOperation。
 
2.其次,你能夠經過下面這些值設置屬性queuePriority來改變執行優先級:
 
3.對於任何給定的隊列,你能夠取消一個特定的或全部的操做。操做能夠在被添加到隊列後被取消。取消是經過調用NSOperation類裏的方法cancel()。當你取消任何操做的時候,咱們有三個場景,其中一個會發生:
你的操做已經完成。在這種狀況下,取消方法沒有效果。
你的操做已經被執行。在這種狀況下,系統不會強制操做代碼中止,而是屬性cancelled被置爲true。
你的操做仍在隊列中等待。在這種狀況下,你的操做將不會被執行。
 
4.NSOperation有3個有用的布爾屬性,finished、 cancelled和ready。一旦操做執行完成,finisher將被置爲true。一旦操做被取消,cancelled將被置爲true。一旦準備即將被執行,ready將被置爲true。
 
5.任何NSOperation有一個選項來設置回調,一旦任務完成將會被調用。在NSOperation裏,一旦屬性finished被置爲true,這個block將被調用。
 
原理探析:
 
demo:
- (void)viewDidLoad {
    [super viewDidLoad];
    // Do any additional setup after loading the view, typically from a nib.
    
    [self configurationQueue];
    LDNSOperation *operation = [[LDNSOperation alloc] init];
    [self.operationQueue addOperation:operation];
    [NSThread sleepForTimeInterval:3];
    [operation cancel];
    
}
 
-(void)configurationQueue{
    self.operationQueue = [[NSOperationQueue alloc] init];
    self.operationQueue.maxConcurrentOperationCount = 4;
}
 
LDNSOperation爲NSOperation的子類,重寫start方法:
-(void)start{
    while (true) {
        if(self.cancelled){
            NSLog(@"已經取消");
            return;
        }
        NSLog(@"start");
        [NSThread sleepForTimeInterval:1];
    }
}
 
 
1.
[self.operationQueue addOperation:operation];
 
添加一個未完成的NSOperation ,其實就是將NSOperation 添加到一個動態的數組中。 
 
 
internal 就是一個內部類,指的是NSOperationQueue 。
使用了KVO手動通知,進行operations 和 operationCount 的改變通知。
 
 
完成的話,就從operations 中刪除。 
若是準備完成,就添加到waiting 中,等待被執行。 
 
_execute 方法:
 
 
若是沒有暫停,就從waiting 中取出第一個,而且刪除waiting 中的這個數據。 
添加isFinished 屬性觀察
若是是併發的話,就立刻執行。 
若是不是,使用detachNewThreadSelector來建立新的線程去執行start。
 
全部的線程都很忙,而且沒有達到threadCount最大值時,會建立新的線程。 
_execute 是一個執行隊列,依次將等待隊列裏全部的operation 進行start 。
 
對於start 函數來說,一個NSOperation 並無新建一個線程。 依然操做在[NSTread currentThread]中。 
 
如今來思考下,也就明白了爲何NSOperationQueue要有兩種處理方式了,若是NSOperation支持併發,而後NSOperationQueue在爲其分配線程,那就是線程裏面又跑了一條線程,這樣就很尷尬了,經過isConcurrent能夠避免這種現象。
相關文章
相關標籤/搜索