2013年7月19日 星期五

iOS-GCD(1)

最近在寫關於PDF的SDK才知道GCD很重要而且常用,平行還真難寫,網路上教學實在很多,瞭解後還是要把寫的樣板背起來,所以先簡單記錄一些平行的樣板八!!
GCD-queue的類型:
queue typedescribe
Main queue main queue工作會依序執行,iOS的UI都是由main thread控制
concurrent queue 還是會依照FIFO的方式來執行,但是有可能後執行的block比先執行的先完成
serial queue 會採用一個接一個的方式來依序執行block

1. All mainThread:此樣板在於把某些task(block)放到main queue,所有的task都在main thread執行
- (IBAction)GCDTest1Btn:(id)sender {
    
    mainQueue = dispatch_get_main_queue();
    
    void (^block1) (void) = ^{
        for(int i = 0;i<10;i++){
            NSLog(@"some block is execute %d time.",i);
        }
    };
    
    void (^block2) (void) = ^{
        for(int i=0;i<10;i++){
            NSLog(@"The other block is execute %d time.",i);
        }
    };
    
    NSLog(@"First block");
    dispatch_async(mainQueue, block1);
    NSLog(@"Second block");
    dispatch_async(mainQueue, block2);
}
因為用的是dispatch_async執行,所以執行完dispatch_async會把block加到main queue後面然後緊接著執行NSLog
上面程式碼執行的示意圖:
執行結果:
2. global queue template:global queue通常是concurrent的queue,搭配dispatcy_async使用
- (IBAction)GCDTest2Btn:(id)sender {
    
    globalQueue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT,0);
    
    void (^block1) (void) = ^{
        for(int i = 0;i<10;i++){
            NSLog(@"some block is execute %d time.",i);
        }
    };
    
    void (^block2) (void) = ^{
        for(int i=0;i<10;i++){
            NSLog(@"The other block is execute %d time.",i);
        }
    };
    
    NSLog(@"First block");
    dispatch_async(globalQueue, block1);
    NSLog(@"Second block");
    dispatch_async(globalQueue, block2);
}
執行結果:
3. 自己定義的queue:該queue的做法是會再開一個thread,然後task會依照該queue在另外的thread執行
- (IBAction)GCDTest3Btn:(id)sender {
    
    myQueue = dispatch_queue_create("myqueue", DISPATCH_QUEUE_SERIAL);
    
    void (^block1) (void) = ^{
        for(int i = 0;i<10;i++){
            NSLog(@"some block is execute %d time.",i);
        }
    };
    
    void (^block2) (void) = ^{
        for(int i=0;i<10;i++){
            NSLog(@"The other block is execute %d time.",i);
        }
    };
    NSLog(@"First block");
    dispatch_async(myQueue, block1);
    NSLog(@"Second block");
    dispatch_async(myQueue, block2);
}
上面的code在會在執行完dispatch_async後緊接著執行NSLog,不會造成阻礙,然後block1和block2會在另外thread執行
上面程式碼執行的示意圖:
執行結果:
4. 一些要避免的deadlock template:寫平行需要小心的就是deadlock,記錄下template
a. queue為main queue:
- (IBAction)GCDTest4Btn:(id)sender {
    
    mainQueue = dispatch_get_main_queue();
    void (^block1) (void) = ^{
        NSLog(@"block1");
    };
    NSLog(@"in main thread");
    dispatch_sync(mainQueue, block1);
}
在上面的程式碼當中,因為使用的是dispatch_sync,其中sync會等該queue中前面的task做完,才能往下繼續執行。

因為共同使用main queue,所以原本的function "GCDTest4Btn" action在main thread上執行,所以task在queue中比block1前面,又因為使用dispatch_sync,所以"GCDTest4Btn" action會等待block1的task完成,然而在queue中,因為是以serial的方式進行,block1在"GCDTest4Btn" action之後,所以會等待該action執行完畢,造成兩個task互相等待,形成deadlock
執行結果:
b. queue為自定的queue
- (IBAction)GCDTest5Btn:(id)sender {
    
    myQueue = dispatch_queue_create("myqueue", DISPATCH_QUEUE_SERIAL);
    NSLog(@"in main queue");
    void (^block1) (void) = ^{
        NSLog(@"block1");
    };
    
    void (^block2) (void) = ^{
    
        NSLog(@"block2");
        dispatch_sync(myQueue, block1);
    };
    NSLog(@"in block1");
    dispatch_sync(myQueue, block1);
    NSLog(@"in block2");
    dispatch_sync(myQueue, block2);
    
}
上面的程式碼概念同a,示意圖如下:
執行結果:
myCode

沒有留言:

張貼留言