1. 程式人生 > >iOS中執行緒的基本介紹(OC)

iOS中執行緒的基本介紹(OC)

一:pthread:基於C

二:NSThread:基於OC

三:GCD:基於C

四:NSOperation:對GCD面向物件的包裝

(一):GCD基本操作:六種任務執行模式

- (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event{

//    //建立序列佇列
//    dispatch_queue_t queue1 = dispatch_queue_create("yhy", DISPATCH_QUEUE_SERIAL);
//    //建立併發佇列
//    dispatch_queue_t queue2 = dispatch_queue_create("yhy", DISPATCH_QUEUE_CONCURRENT);
// //建立主佇列(非同步函式放在主佇列中是不會開執行緒的,將任務放在主執行緒中執行) // dispatch_queue_t queue3 = dispatch_get_main_queue(); // //建立全域性佇列(全域性併發佇列) // dispatch_queue_t queue4 = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0); // //總結: //同步+併發 == 不能開執行緒(序列執行任務) //同步+序列 == 不能開執行緒(任務序列,在當前執行緒中執行任務) //非同步+併發 == 可以開執行緒(開多個執行緒,任務並行,會開多個執行緒執行任務)
//非同步+序列 == 可以開執行緒(開一個執行緒,任務序列,會開一個執行緒執行任務) //同步+主佇列 == 不能開執行緒(主執行緒中執行任務) //非同步+主佇列 == 不能開現場(在主執行緒中執行任務) //建立執行緒 // [self synchronizeMain]; // [self synchronizeSerial]; // // [self synchronizeConcurrent]; // [self asynchronizeMain]; // // [self asynchronizeSerial]; // // [self asynchronizeConcurrent];
} //下面每一種情況有四個任務 //同步+序列(序列佇列派發的任務不需要等待同步函式執行完之後再執行,可以先執行,這就是為什麼最後才會執行NSLog(@"以上所有的任務開始執行")) - (void)synchronizeSerial{ dispatch_queue_t queue = dispatch_queue_create("yhy", DISPATCH_QUEUE_SERIAL);//DISPATCH_QUEUE_SERIAL == null dispatch_sync(queue, ^{ NSLog(@"1------%@",[NSThread currentThread]); }); dispatch_sync(queue, ^{ NSLog(@"2------%@",[NSThread currentThread]); }); dispatch_sync(queue, ^{ NSLog(@"3------%@",[NSThread currentThread]); }); dispatch_sync(queue, ^{ NSLog(@"4------%@",[NSThread currentThread]); }); NSLog(@"以上所有的任務開始執行"); } //同步+併發(由於併發佇列就是全域性佇列,那麼所有的併發佇列由全域性佇列代替,效果和同步+序列一樣的) - (void)synchronizeConcurrent{ dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0); dispatch_sync(queue, ^{ NSLog(@"1-----%@",[NSThread currentThread]); }); dispatch_sync(queue, ^{ NSLog(@"2-----%@",[NSThread currentThread]); }); dispatch_sync(queue, ^{ NSLog(@"3-----%@",[NSThread currentThread]); }); dispatch_sync(queue, ^{ NSLog(@"4-----%@",[NSThread currentThread]); }); NSLog(@"以上所有的任務開始執行"); } //同步+主佇列(會造成死鎖,原有是因為:整個同步函式就是一個任務,但是在主佇列中的任務會被排程到主執行緒中執行,那麼這個任務就排在了同步函式這個任務之後,但是主執行緒中的任務需要一個一個的執行,當執行到主佇列派發的任務的時候,這個任務又需要主執行緒將同步函式這個任務執行完畢之後才能執行,那麼主佇列派發的任務就不能執行,同步函式這個任務也不能執行,那麼就死鎖了) - (void)synchronizeMain{ NSLog(@"dd"); dispatch_queue_t queue = dispatch_get_main_queue(); dispatch_sync(queue, ^{ NSLog(@"1------%@",[NSThread currentThread]); }); NSLog(@"dd"); dispatch_sync(queue, ^{ NSLog(@"2------%@",[NSThread currentThread]); }); dispatch_sync(queue, ^{ NSLog(@"3------%@",[NSThread currentThread]); }); dispatch_sync(queue, ^{ NSLog(@"4------%@",[NSThread currentThread]); }); NSLog(@"以上所有的任務開始執行"); } //非同步+序列(開一條執行緒,任務線上程中一個一個的執行) - (void)asynchronizeSerial{ dispatch_queue_t queue = dispatch_queue_create("yhy", DISPATCH_QUEUE_SERIAL); dispatch_async(queue, ^{ NSLog(@"1------%@",[NSThread currentThread]); }); dispatch_async(queue, ^{ NSLog(@"2------%@",[NSThread currentThread]); }); dispatch_async(queue, ^{ NSLog(@"3------%@",[NSThread currentThread]); }); dispatch_async(queue, ^{ NSLog(@"4------%@",[NSThread currentThread]); }); NSLog(@"以上所有的任務開始執行"); } //非同步+併發(開啟多條執行緒,任務在不同的執行緒中併發執行) - (void)asynchronizeConcurrent{ dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0); dispatch_async(queue, ^{ NSLog(@"1-------%@",[NSThread currentThread]); }); dispatch_async(queue, ^{ NSLog(@"2-------%@",[NSThread currentThread]); }); dispatch_async(queue, ^{ NSLog(@"3-------%@",[NSThread currentThread]); }); dispatch_async(queue, ^{ NSLog(@"4-------%@",[NSThread currentThread]); }); NSLog(@"以上所有的任務開始執行"); } //非同步+主佇列(不會開執行緒,在主執行緒中一個一個的執行) - (void)asynchronizeMain{ dispatch_queue_t queue = dispatch_get_main_queue(); dispatch_async(queue, ^{ NSLog(@"1-------%@",[NSThread currentThread]); }); dispatch_async(queue, ^{ NSLog(@"2-------%@",[NSThread currentThread]); }); dispatch_async(queue, ^{ NSLog(@"3-------%@",[NSThread currentThread]); }); dispatch_async(queue, ^{ NSLog(@"4-------%@",[NSThread currentThread]); }); NSLog(@"以上所有的任務開始執行"); }

(二):GCD通訊:不同執行緒之間相互通訊

- (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event
{
 //將需要耗時的操作放在子執行緒中,將UI中的圖片顯示放在主執行緒中   dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{

        NSURL *url = [NSURL URLWithString:@"http://pic10.nipic.com/20101001/4438138_140843092127_2.jpg"];

        NSURL *url1 = [NSURL URLWithString:@"http://e.hiphotos.baidu.com/baike/pic/item/72f082025aafa40f77ca4ed5ab64034f78f019ad.jpg"];

        NSData *data1 = [NSData dataWithContentsOfURL:url1];

        NSData *data = [NSData dataWithContentsOfURL:url];

        //回到主執行緒
        dispatch_async(dispatch_get_main_queue(), ^{

            self.imageView.image = [UIImage imageWithData:data];

            self.imageView1.image = [UIImage imageWithData:data1];

        });


    });


}

(三):GCD中的方法:dispatch_barrier方法

- (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event{

    for (int i = 0; i < 10;  i++) {

        dispatch_group_t group = dispatch_group_create();

        dispatch_queue_t queue = dispatch_queue_create("yhy", DISPATCH_QUEUE_CONCURRENT);

    dispatch_async(queue, ^{

        NSLog(@"1---------%@",[NSThread currentThread]);

    });
    dispatch_async(queue, ^{

        NSLog(@"2---------%@",[NSThread currentThread]);

    });
    //這個barrier函式就是先讓前面所有的任務執行玩之後,再執行它自己,再執行後面的任務,但是queue不能是全域性併發佇列

    dispatch_barrier_sync(queue, ^{

        NSLog(@"barrier-----------");


    });

    dispatch_async(queue, ^{

        NSLog(@"3---------%@",[NSThread currentThread]);

    });  dispatch_async(queue, ^{

        NSLog(@"4---------%@",[NSThread currentThread]);

    });

    }

    NSLog(@"sasfgd");
}

(四):GCD中的方法:dispatch_once方法

//這裡沒有詳細的介紹,今後在swift3中,在面向物件的GCD中再詳細介紹
static Person *_person;

+ (instancetype)allocWithZone:(struct _NSZone *)zone
{
    //這個方法表面,[super alloc]只會呼叫一次
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{

       _person  = [super allocWithZone:zone];


    });

    return _person;
}

(五):GCD:佇列組

- (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event{
    //建立組物件
    dispatch_group_t group = dispatch_group_create();

    //建立佇列物件
    dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
    //建立佇列組
    dispatch_group_async(group, queue,  ^{

        NSURL *url = [NSURL URLWithString:@"http://img1c.xgo-img.com.cn/pics/1717/1716083.jpg"];

        NSData *data = [NSData dataWithContentsOfURL:url];

        UIImage *image = [UIImage imageWithData:data];

        self.image1 = image;

    });


    dispatch_group_async(group, queue, ^{

        NSURL *url = [NSURL URLWithString:@"http://img1c.xgo-img.com.cn/pics/1717/1716083.jpg"];

        NSData *data = [NSData dataWithContentsOfURL:url];

        UIImage *image = [UIImage imageWithData:data];

        self.image2 = image;


    });

    //當佇列組中的任務執行完成之後,才會會呼叫這個方法,這樣佇列組就避免了獲取圖形上下文的點陣圖的任務在載入圖片的任務之前執行
 dispatch_group_notify(group, queue, ^{

     //獲得圖形上下文
     UIGraphicsBeginImageContext(CGSizeMake(200, 200));

     //繪製圖片
     [self.image1 drawInRect:CGRectMake(0, 0, 100, 200)];

     [self.image2 drawInRect:CGRectMake(100, 0, 100, 200)];

     //拿到圖形上下文的點陣圖
     UIImage *image = UIGraphicsGetImageFromCurrentImageContext();

     dispatch_async(dispatch_get_main_queue(), ^{

         _imageView.image = image;

     });

     //關閉上下文呢

     UIGraphicsEndImageContext();

 });

(六):GCD:單例模式

通過GCD實現的單例模式,也就是通過dispatch_once來實現的,將單例抽成巨集,給單例的申明和實現取一個別名