多線程

一、NSthread的初始化

1.動態(tài)方法

-(id)initWithTarget:(id)target selector:(SEL)selector object:(id)argument;
// 初始化線程
NSThread *thread = [[NSThread alloc] initWithTarget:self selector:@selector(run) object:nil];
// 設(shè)置線程的優(yōu)先級(0.0 - 1.0,1.0最高級)
thread.threadPriority = 1;
// 開啟線程
[thread start];

參數(shù)解析:
selector :線程執(zhí)行的方法,這個selector最多只能接收一個參數(shù)
target :selector消息發(fā)送的對象
argument : 傳給selector的唯一參數(shù),也可以是nil

2.靜態(tài)方法

+ (void)detachNewThreadSelector:(SEL)selector toTarget:(id)target withObject:(id)argument;  
[NSThread detachNewThreadSelector:@selector(downloagImage:) toTarget:self withObject:@"http://h.hiphotos.baidu.com/zhidao/pic/item/6a63f6246b600c3320b14bb3184c510fd8f9a185.jpg"];
-(void)downloagImage:(NSString*)url
{
    NSData *data = [[NSData alloc] initWithContentsOfURL:[NSURL URLWithString:url]];
    UIImage *image= [[UIImage alloc] initWithData:data];
    if (image) {
       [self performSelectorOnMainThread:@selector(updateUI:) withObject:image waitUntilDone:YES];
   }
}

3.隱式創(chuàng)建線程的方法

[self performSelectorInBackground:@selector(run) withObject:nil];  

4.獲取當(dāng)前線程

NSThread *current = [NSThread currentThread];  

5.獲取主線程

NSThread *main = [NSThread mainThread];  

6.在指定線程上執(zhí)行操作

[self performSelector:@selector(run) onThread:thread withObject:nil waitUntilDone:YES];  

7.在主線程上執(zhí)行操作

[self performSelectorOnMainThread:@selector(run) withObject:nil waitUntilDone:YES];  

8.在當(dāng)前線程執(zhí)行操作

[self performSelector:@selector(run) withObject:nil];  

9.優(yōu)缺點

1.優(yōu)點:NSThread比其他兩種多線程方案較輕量級,更直觀地控制線程對象
2.缺點:需要自己管理線程的生命周期,線程同步。線程同步對數(shù)據(jù)的加鎖會有一定的系統(tǒng)開銷

GCD

二、GCD

6種
并行隊列 + 同步執(zhí)行(不會開啟新線程)
并行隊列 + 異步執(zhí)行(可同時開啟多線程,任務(wù)交替執(zhí)行)
串行隊列 + 同步執(zhí)行(不會開啟新線程)
串行隊列 + 異步執(zhí)行(可同時開啟多線程)
主隊列 + 同步執(zhí)行 ***互等卡住不可行
主隊列 + 異步執(zhí)行 ***執(zhí)行完一個任務(wù),再執(zhí)行下一個任務(wù)

// 串行隊列的創(chuàng)建方法
dispatch_queue_t queue= dispatch_queue_create("test.queue", DISPATCH_QUEUE_SERIAL);
// 并行隊列的創(chuàng)建方法
dispatch_queue_t queue= dispatch_queue_create("test.queue", DISPATCH_QUEUE_CONCURRENT);
// 同步執(zhí)行任務(wù)創(chuàng)建方法
dispatch_sync(queue, ^{
    NSLog(@"%@",[NSThread currentThread]);    // 這里放任務(wù)代碼
});
// 異步執(zhí)行任務(wù)創(chuàng)建方法
dispatch_async(queue, ^{
    NSLog(@"%@",[NSThread currentThread]);    // 這里放任務(wù)代碼
});

1.柵欄方法 dispatch_barrier_async,在執(zhí)行完柵欄前面的操作之后,才執(zhí)行柵欄操作,最后再執(zhí)行柵欄后邊的操作

dispatch_barrier_async(queue, ^{
        NSLog(@"----barrier-----%@", [NSThread currentThread]);
});

2.延時執(zhí)行方法 dispatch_after

dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(2.0 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
    // 2秒后異步執(zhí)行這里的代碼...
   NSLog(@"run-----");
});

3.一次性代碼(只執(zhí)行一次) dispatch_once(單例)

static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
    // 只執(zhí)行1次的代碼(這里面默認是線程安全的)
});

4.快速迭代方法 dispatch_apply

dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
dispatch_apply(6, queue, ^(size_t index) {
    NSLog(@"%zd------%@",index, [NSThread currentThread]);
});

5.隊列組 dispatch_group

dispatch_group_t group =  dispatch_group_create();
dispatch_group_async(group, dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
    // 執(zhí)行1個耗時的異步操作
});
dispatch_group_async(group, dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
    // 執(zhí)行1個耗時的異步操作
});
dispatch_group_notify(group, dispatch_get_main_queue(), ^{
    // 等前面的異步操作都執(zhí)行完畢后,回到主線程...
});

三、NSOperation

1. 使用子類- NSInvocationOperation:

// 1.創(chuàng)建NSInvocationOperation對象
NSInvocationOperation *op = [[NSInvocationOperation alloc] initWithTarget:self selector:@selector(run) object:nil];

// 2.調(diào)用start方法開始執(zhí)行操作
[op start];
- (void)run
{
    NSLog(@"------%@", [NSThread currentThread]);
}

在沒有使用NSOperationQueue、單獨使用NSInvocationOperation的情況下,NSInvocationOperation在主線程執(zhí)行操作,并沒有開啟新線程

2.使用子類- NSBlockOperation

NSBlockOperation *op = [NSBlockOperation blockOperationWithBlock:^{
    // 在主線程
    NSLog(@"------%@", [NSThread currentThread]);
}];
[op start];

在沒有使用NSOperationQueue、單獨使用NSBlockOperation的情況下,NSBlockOperation也是在主線程執(zhí)行操作,并沒有開啟新線程
但是,NSBlockOperation還提供了一個方法addExecutionBlock:,通過addExecutionBlock:就可以為NSBlockOperation添加額外的操作,這些額外的操作就會在其他線程并發(fā)執(zhí)行。

- (void)blockOperation
{
    NSBlockOperation *op = [NSBlockOperation blockOperationWithBlock:^{
        // 在主線程
        NSLog(@"1------%@", [NSThread currentThread]);
    }];    

    // 添加額外的任務(wù)(在子線程執(zhí)行)
    [op addExecutionBlock:^{
        NSLog(@"2------%@", [NSThread currentThread]);
    }];
    [op addExecutionBlock:^{
        NSLog(@"3------%@", [NSThread currentThread]);
    }];
    [op addExecutionBlock:^{
        NSLog(@"4------%@", [NSThread currentThread]);
    }];

    [op start];
}

blockOperationWithBlock:方法中的操作是在主線程中執(zhí)行的,而addExecutionBlock:方法中的操作是在其他線程中執(zhí)行的

3.將任務(wù)加入到隊列中

(1).- (void)addOperation:(NSOperation *)op;需要先創(chuàng)建任務(wù),再將創(chuàng)建好的任務(wù)加入到創(chuàng)建好的隊列中去

- (void)addOperationToQueue
{
    // 1.創(chuàng)建隊列
    NSOperationQueue *queue = [[NSOperationQueue alloc] init];

    // 2. 創(chuàng)建操作  
    // 創(chuàng)建NSInvocationOperation    
    NSInvocationOperation *op1 = [[NSInvocationOperation alloc] initWithTarget:self selector:@selector(run) object:nil];    
    // 創(chuàng)建NSBlockOperation    
    NSBlockOperation *op2 = [NSBlockOperation blockOperationWithBlock:^{
        for (int i = 0; i < 2; ++i) {
            NSLog(@"1-----%@", [NSThread currentThread]);
        }
    }];

    // 3. 添加操作到隊列中:addOperation:   
    [queue addOperation:op1]; // [op1 start]    
    [queue addOperation:op2]; // [op2 start]
}

- (void)run
{
    for (int i = 0; i < 2; ++i) {
        NSLog(@"2-----%@", [NSThread currentThread]);
    }
}

NSInvocationOperation和NSOperationQueue結(jié)合后能夠開啟新線程,進行并發(fā)執(zhí)行NSBlockOperation和NSOperationQueue也能夠開啟新線程,進行并發(fā)執(zhí)行
(2).- (void)addOperationWithBlock:(void (^)(void))block;無需先創(chuàng)建任務(wù),在block中添加任務(wù),直接將任務(wù)block加入到隊列中

- (void)addOperationWithBlockToQueue
{
    // 1. 創(chuàng)建隊列
    NSOperationQueue *queue = [[NSOperationQueue alloc] init];

    // 2. 添加操作到隊列中:addOperationWithBlock:
    [queue addOperationWithBlock:^{
        for (int i = 0; i < 2; ++i) {
            NSLog(@"-----%@", [NSThread currentThread]);
        }
    }];
}

能夠開啟新線程,進行并發(fā)執(zhí)行

4.控制串行執(zhí)行和并行執(zhí)行的關(guān)鍵

最大并發(fā)數(shù):maxConcurrentOperationCount
maxConcurrentOperationCount默認情況下為-1,表示不進行限制,默認為并發(fā)執(zhí)行。
當(dāng)maxConcurrentOperationCount為1時,進行串行執(zhí)行。
當(dāng)maxConcurrentOperationCount大于1時,進行并發(fā)執(zhí)行,當(dāng)然這個值不應(yīng)超過系統(tǒng)限制,即使自己設(shè)置一個很大的值,系統(tǒng)也會自動調(diào)整。

// 創(chuàng)建隊列
    NSOperationQueue *queue = [[NSOperationQueue alloc] init];

    // 設(shè)置最大并發(fā)操作數(shù)
    //    queue.maxConcurrentOperationCount = 2;
    queue.maxConcurrentOperationCount = 1; // 就變成了串行隊列

5.操作依賴

NSOperation和NSOperationQueue最吸引人的地方是它能添加操作之間的依賴關(guān)系。比如說有A、B兩個操作,其中A執(zhí)行完操作,B才能執(zhí)行操作,那么就需要讓B依賴于A。具體如下

- (void)addDependency
{
    NSOperationQueue *queue = [[NSOperationQueue alloc] init];

    NSBlockOperation *op1 = [NSBlockOperation blockOperationWithBlock:^{
        NSLog(@"1-----%@", [NSThread  currentThread]);
    }];
    NSBlockOperation *op2 = [NSBlockOperation blockOperationWithBlock:^{
        NSLog(@"2-----%@", [NSThread  currentThread]);
    }];

    [op2 addDependency:op1];    // 讓op2 依賴于 op1,則先執(zhí)行op1,在執(zhí)行op2

    [queue addOperation:op1];
    [queue addOperation:op2];
}

6.一些其他方法

- (void)cancel;NSOperation提供的方法,可取消單個操作
- (void)cancelAllOperations;NSOperationQueue提供的方法,可以取消隊列的所有操作
- (void)setSuspended:(BOOL)b;可設(shè)置任務(wù)的暫停和恢復(fù),YES代表暫停隊列,NO代表恢復(fù)隊列
- (BOOL)isSuspended;判斷暫停狀態(tài)
注意:
這里的暫停和取消并不代表可以將當(dāng)前的操作立即取消,而是當(dāng)當(dāng)前的操作執(zhí)行完畢之后不再執(zhí)行新的操作。
暫停和取消的區(qū)別就在于:暫停操作之后還可以恢復(fù)操作,繼續(xù)向下執(zhí)行;而取消操作之后,所有的操作就清空了,無法再接著執(zhí)行剩下的操作。

以上部分資料感謝http://www.itdecent.cn/p/4b1d77054b35

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • 發(fā)現(xiàn) 關(guān)注 消息 iOS 第三方庫、插件、知名博客總結(jié) 作者大灰狼的小綿羊哥哥關(guān)注 2017.06.26 09:4...
    肇東周閱讀 15,158評論 4 61
  • Android 自定義View的各種姿勢1 Activity的顯示之ViewRootImpl詳解 Activity...
    passiontim閱讀 178,881評論 25 709
  • 近了,近了繞過這座山,越過那條河就快到了走上這條小路,拐幾個彎就到了 你看那被群山環(huán)抱著的小村落,就是我的家鄉(xiāng)。生...
    采漪閱讀 361評論 0 2
  • 多肉植物老樁系列 銀手指 這樣的也不多見 關(guān)注多肉花客
    多肉花客閱讀 2,161評論 0 0
  • 每周日的輸出我打算從文章里抄寫一些我認為有價值的信息。 以下摘自《自控力》。 意志力實驗:5分鐘訓(xùn)練大腦冥想 專心...
    小橙小橙小橙閱讀 118評論 0 0

友情鏈接更多精彩內(nèi)容