IOS三種線程技術各自優缺點

   大家都知道,多線程提(多核心)高了計算機的處理速度。我對這一塊有淺淺的認識,跟大家分享:

首先 大家要注意  1 、線程的使用不是無節制的 2、只有主線程有直接修改UI的能力。

IOS的三種多線程技術:

                 一 、NSThread 是每個NSThread對象對應一個線程,輕量級的。是對pthread(其是POSIX線程的API,是C語言的技術,當                        然它可以直接操作線程)的抽象。

             二、 GCD(Grand Central Dispatch)是基於C語言的框架,使用隊列來管理線程,它可以充分利用多核。

             三、NSOperation/NSOperationQueue是面向對象的線程技術,是對GCD的抽象,容易理解和使用。

三種線程的對比 

             NSThread 、   優點:使用特別簡單。

                               缺點:需要自己來管理線程的生命週期、線程同步、加鎖、睡眠和喚醒。過程不可避免的有一定的系統“開銷”;

             NSOperation、優點:不用關心線程的管理和數據的同步,把精力放在自己需要執行的任務或操作上就行了

                                     而且它是面向對象的;

             GCD、            優點:Grand Central Dispatch是由蘋果公司開發的一個多核編程解決方案。IOS4.0以後才能使用,是代替上面兩個技                                      術的高效而且強大的技術。它基於block的特性導致它能極爲簡單的在不同代碼作用域之間傳遞上下文。效率高。性能:    GCD自動根據系統負載來增減線程數量,這就減少了上下文的切換和提高了計算效率。安全  無需加鎖或其他同步機制。(看起來就很高大上嘛。)

                                   它是基於C語言的;

NSThread 創建與啓動

    //第1種 調用mutableThread方法
    NSThread *thread = [[NSThread alloc] initWithTarget:self selector:@selector(mutableThread) object:nil];
    [thread start];
    //第2種 調用mutableThread方法
    [NSThread detachNewThreadSelector:@selector(mutableThread) toTarget:self withObject:nil];
    //第3種 調用mutableThread方法
    [self performSelectorInBackground:@selector(mutableThread) withObject:nil];
<span style="font-size: 14px;">NSThread 的常用方法</span>
//獲取當前線程對象
+(NSThread *)currentThread;
//判斷當前線程是否爲主線程
+(BOOL)isMainThread;
//使當前線程睡眠指定的時間  單位 S
+(void)sleepForTimeInterval:(NSTimeInterval)timeMiao;
//退出當前線程
+(void)exit;
//啓動該線程
- (void)start;
        注意:NSThread  可以直接使用線程,但是當你的代碼和框架中都創建自己的線程時,那麼活動線程會指數增長,雖然每塊沒有問題,但是結果就導致問題。而且使用線程會消耗一些內存和內核資源


線程隊列NSOperationQueue

//1 block
    NSOperationQueue *queue = [[NSOperationQueue alloc] init];
    [queue addOperationWithBlock:^{
        NSThread *thread = [NSThread currentThread];
        if (![thread isMainThread]) {
            NSLog(@"這是個多線程");
        }
    }];
    //2 NSOPeration 開啓一個線程
    NSOperationQueue *threadQueue = [[NSOperationQueue alloc] init];
    NSInvocationOperation *op = [[NSInvocationOperation alloc] initWithTarget:self selector:@selector(mutableThread) object:nil];
    [threadQueue addOperation:op];
    //3在主線程上調用reloadData方法
    [self performSelectorOnMainThread:@selector(reloadData) withObject:nil waitUntilDone:NO];

GCD:

Dispatch Queue

Dispatch Queue 是執行處理的等待隊列。通過dispatch_async等函數,按照先進先出順序追加到Queue中處理

處理的時候Dispatch Queue有兩種

1.Serial Dispatch Queue 等待現在正在執行的任務處理結束(串行)

2.Concurrent Dispatch Queue 不等帶現在正在執行的任務的任務處理結束(並行、併發)

//1.
    //定義想要執行的操作(任務),追加到適當的隊列中(Dispatch Queue)
    //GCD簡單用法
    /*
    dispatch_async(queue, ^{
        ;
    });
     */
    //(1)追加的隊列
    //(2)block 要執行的任務
    
    //2.Queue類型
    //(1)Serial Dispatch Queue --- 等待現在正在執行的任務處理結束(串行)
    //(2)Concurrent Dispatch Queue --- 不等待現在正在執行的任務處理結束(並行、併發)
    
    
    //3.自己定義queue,把任務加到自定義的queue之中
    /*
    //(1)創建queue
    //第一個參數:給隊列起名字
    //第二個參數:queue的類型 (默認是串行的)
    dispatch_queue_t queue1 = dispatch_queue_create("com.wxhl.gcd.Queue1", NULL);
    
    dispatch_queue_t queue2 = dispatch_queue_create("com.wxhl.gcd.Queue2", DISPATCH_QUEUE_CONCURRENT);  //並行的queue
    
    //(2)創建要執行的任務,加到queue中執行
    dispatch_async(queue2, ^{
        for (int i = 0; i < 50; i ++) {
            NSLog(@"GCD : %d", i);
        }
    });
    
    dispatch_async(queue2, ^{
        for (int i = 0; i < 50; i ++) {
            NSLog(@"GCD2------ : %d", i);
        }
    });
    
    //ARC會自動管理內存
//    dispatch_release(queue1);
//    dispatch_retain(queue1);
    
    */
Dispatch After:
  //Dispatch After
    //一段時間之後,把要執行的任務追加到隊列當中
    
    //創建時間
    //相對的時間點     相對第一個參數多長時間之後
    dispatch_time_t time = dispatch_time(DISPATCH_TIME_NOW, 3ull * NSEC_PER_SEC);
    
    //時間的單位
    //NSEC_PER_SEC   秒
    //NSEC_PER_MSEC  毫秒
    //NSEC_PER_USEC  微秒
    
    //dispatch_time_t 指定的時間
    dispatch_after(time, dispatch_get_main_queue(), ^{
        NSLog(@"after 3s");
    });
    
    //第二種用法
    dispatch_after_f(dispatch_time(DISPATCH_TIME_NOW, 3ull * NSEC_PER_SEC), dispatch_get_main_queue(), NULL, func1);
    
    
    //自己使用
    dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(5ull * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
        ;
    });
    
#warning 注意
    //1.不是一段時間之後執行相應的任務 (而是把要執行的任務追加到隊列當中)
    //2.主線程 runloop 1/60秒檢測事件, 追加的時間範圍 3s - (3 + 1/60)s
dispatch group:(它的第二種監測方法是通過時間 去檢測(比如5秒),但是它只是在5秒後去看一次,沒有執行完和執行完  做出的響應分爲兩個。我還沒有發現這個方法的應用實例,我做的項目非常少,可能以後會用上,也很簡單)
    //並行隊列執行任務, 多個串行的隊列
    //dispatch group
    
    //1.創建 group
    dispatch_group_t group = dispatch_group_create();
    
    //2.獲取隊列
    dispatch_queue_t queue = dispatch_get_global_queue(0, 0);
    
    //3.使用 group 監視 隊列任務的執行
    dispatch_group_async(group, queue, ^{
        NSLog(@"task 1");
    });
    
    dispatch_group_async(group, queue, ^{
        NSLog(@"task 2");
    });
    
    dispatch_group_async(group, queue, ^{
        NSLog(@"task 3");
    });
    
    dispatch_group_async(group, queue, ^{
        sleep(6);
        NSLog(@"task 4");
    });
    
    
    //(1)監視的函數
    //監視到隊列裏任務執行結束,執行block裏面的任務
    dispatch_group_notify(group, queue, ^{
        //結束處理
        NSLog(@"done");
    });

dispatch sync/dispatch async    dispatch sync 容易遇見死鎖問題,一般熟練者用(我不行)
 //dispatch sync
    //
    
    //async: asynchronous 將任務異步的追加到隊列中
    dispatch_async(dispatch_get_global_queue(0, 0), ^{
        NSLog(@"async");
    });
    
    //sync: synchronous 將任務同步的追加到隊列中(等隊列中的任務執行完,再將任務追加到隊列)
    //是同步追加,不是任務同步執行,在串行隊列中,任務才同步執行
    dispatch_sync(dispatch_get_global_queue(0, 0), ^{
        NSLog(@"sync");
    });
    
    
    //dispatch_sync的問題:容易產生死鎖
    //示例1:
    dispatch_sync(dispatch_get_main_queue(), ^{
        NSLog(@"hello");
    });
    
    NSLog(@"主線程");
    
    //上述代碼在主隊列中執行指定的block,等待其執行結束
    //而主隊列中本來就在執行上述代碼,無法執行追加的block
    
    //示例2:
    //串行的隊列
    dispatch_queue_t queue = dispatch_queue_create("com.wxhl.GCD.queue", NULL);
    dispatch_async(queue, ^{
        dispatch_sync(queue, ^{
            NSLog(@"串行隊列");
        });
    });
<span style="font-size:24px;">Dispatch Semaphore</span>
  //Dispatch Semaphore
    //持有計數的信號
    //1.計數爲0時,等待
    //2.計數大於等於1時,減去1,而且不等待
    
    //使用
    dispatch_queue_t queue = dispatch_get_global_queue(0, 0);
    
    dispatch_semaphore_t dsema = dispatch_semaphore_create(1);
    
    NSMutableArray *array = [NSMutableArray array];
    
    for (int i = 0; i < 1000; i++) {
        dispatch_async(queue, ^{
            dispatch_semaphore_wait(dsema, DISPATCH_TIME_FOREVER);
            
            [array addObject:[NSNumber numberWithInt:i]];
            
            dispatch_semaphore_signal(dsema);
            
        });
    }



發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章