国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁 > 學院 > 開發設計 > 正文

iOS多線程--GCD

2019-11-14 18:33:20
字體:
來源:轉載
供稿:網友

簡單介紹下GCD:

GCD:Grand Central Dispatch(偉大的中樞調度器),純C的函數,提供了很多非常強大的功能。

它是蘋果公司為多核的并行運算提出的解決方案,具有以下優點

1.GCD會自動利用更多的CPU內核(雙核、四核等)

2.自動管理線程的生命周期(創建任務、調度任務、銷毀線程)

3.程序員只需要告訴GCD想要執行什么任務,不需要編寫任何線程管理代碼,所以它大大解放了程序員

在GCD中有兩個核心的概念:任務和隊列。任務就是你要執行什么操作 隊列就是用來存放任務

使用GCD一般有兩個步驟:

1.定制任務,確定你要進行的操作

2.將任務添加到隊列中,GCD會自動將任務從隊列中取出(FIFO,先進先出原則),放到相應的線程中執行

GCD中有兩個主要執行任務的函數:

1.同步:(不能開啟新線程)

dispatch_sync(dispatch_queue_t queue, dispatch_block_t block)

2.異步:(開啟新線程)

dispatch_async(dispatch_queue_t queue, dispatch_block_t block)

GCD中的隊列有可以分為兩大類型:

1.并發隊列(Concurrent Dispatch Queue):可以讓多個任務并發(同時)執行(自動開啟多個線程執行任務),并發功能只有在異步函數下才有效(dispatch_async)

2.串行隊列:任務一個接一個有序執行

GCD默認已經提供了全局的并發隊列,供整個應用使用,不需要手動創建:使用dispatch_get_global_queue函數獲得全局的并發隊列

串行隊列有兩種方式獲得:1.dispatch_queue_create創建 2.使用主隊列dispatch_get_main_queue(),主隊列是GCD自帶的一種特殊的串行隊列,放在主隊列的任務都會在主線程中執行

上代碼驗證下:

1.異步函數在并發隊列中執行

- (void)viewDidLoad {    [super viewDidLoad];        // 1.獲得全局的并發隊列    dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);    // 2.添加任務到隊列中執行任務    dispatch_async(queue, ^{        NSLog(@"下載1----%@",[NSThread currentThread]);    });    dispatch_async(queue, ^{        NSLog(@"下載2----%@",[NSThread currentThread]);    });    dispatch_async(queue, ^{        NSLog(@"下載3----%@",[NSThread currentThread]);    });};

結果如圖:

可見程序在多線程中并發執行

2.異步函數在串行隊列中執行:

- (void)viewDidLoad {    [super viewDidLoad];    [self asyncSerialQueue];}#pragma mark 異步+串行-(void)asyncSerialQueue{    // 1.創建串行隊列    dispatch_queue_t queue = dispatch_queue_create("gcd.queue", NULL);    // 2.添加任務到隊列中執行任務    dispatch_async(queue, ^{        NSLog(@"下載1----%@",[NSThread currentThread]);    });    dispatch_async(queue, ^{        NSLog(@"下載2----%@",[NSThread currentThread]);    });    dispatch_async(queue, ^{        NSLog(@"下載3----%@",[NSThread currentThread]);    });}

結果如圖:

可見程序開啟單個線程按順序執行

3.在同步函數中執行并發任務

- (void)viewDidLoad {    [super viewDidLoad];    [self syncConcurrentQueue];}#pragma mark 同步+并發-(void)syncConcurrentQueue{    // 1.獲得全局的并發隊列    dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);        // 2.添加任務到隊列中執行任務    dispatch_sync(queue, ^{        NSLog(@"下載1----%@",[NSThread currentThread]);    });    dispatch_sync(queue, ^{        NSLog(@"下載2----%@",[NSThread currentThread]);    });    dispatch_sync(queue, ^{        NSLog(@"下載3----%@",[NSThread currentThread]);    });}

結果如圖:

在主線程中按順序執行,并發隊列失去并發功能

4.同步執行串行隊列:

- (void)viewDidLoad {    [super viewDidLoad];    [self syncSerialQueue];}#pragma mark 同步+串行-(void)syncSerialQueue{    // 1.創建串行隊列    dispatch_queue_t queue = dispatch_queue_create("gcd.queue", NULL);    // 2.添加任務到隊列中執行任務    dispatch_sync(queue, ^{        NSLog(@"下載1----%@",[NSThread currentThread]);    });    dispatch_sync(queue, ^{        NSLog(@"下載2----%@",[NSThread currentThread]);    });    dispatch_sync(queue, ^{        NSLog(@"下載3----%@",[NSThread currentThread]);    });}

結果同第三種情況,不會開啟新的線程,按順序執行

這里要特別注意,如果使用同步函數在主隊列中執行,會造成線程死鎖的情況

- (void)viewDidLoad{    [super viewDidLoad];        NSLog(@"1");    dispatch_sync(dispatch_get_main_queue(), ^{        NSLog(@"2");    });    NSLog(@"3");}

輸出結果為1

那么使用異步函數在主隊列中執行呢?

- (void)viewDidLoad{    [super viewDidLoad];        NSLog(@"1----%@",[NSThread currentThread]);    dispatch_async(dispatch_get_main_queue(), ^{        NSLog(@"2----%@",[NSThread currentThread]);    });    NSLog(@"3----%@",[NSThread currentThread]);}

結果為:

結果很特殊:不會開啟新的線程,而是主隊列中的任務會緩一緩,最后執行

綜上來看,各種隊列執行情況如下表:

關于GCD還有其他用法

1.延時執行:

- (void)viewDidLoad{    [super viewDidLoad];        // 通常的延時執行    dispatch_async(dispatch_get_main_queue(), ^{        [self performSelector:@selector(run) withObject:nil afterDelay:1.0];    });        // gcd函數執行    dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);    dispatch_time_t when = dispatch_time(DISPATCH_TIME_NOW, (int64_t)(1.0 * NSEC_PER_SEC));    dispatch_after(when, queue ^{        [self run];    });    }

 

2.保證某段代碼在執行過程中只執行一次(可用于實現單例模式):

- (void)viewDidLoad{    [super viewDidLoad];    static dispatch_once_t onceToken;    dispatch_once(&onceToken, ^{        // 執行一次的操作代碼    });    }

 

3.隊列組(通常用于耗時操作)

例如下載兩張圖片,要等兩張圖片都下載完成后,合并兩張圖,再更新主界面。由于下載圖片時間長短不可控,使用普通方法會很困難,這時使用隊列組可高效解決

- (void)viewDidLoad{    [super viewDidLoad];    // 創建一個組    dispatch_group_t group = dispatch_group_create();    // 下載圖片1    __block UIImage *image1 = nil;    dispatch_group_async(group, dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{        image1 = [self downloadImageWithUrl:@"https://www.baidu.com/img/bdlogo.png"];    });    // 下載圖片2    __block UIImage *image2 = nil;    dispatch_group_async(group, dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{        image2 = [self downloadImageWithUrl:@"http://img1.bdstatic.com/static/home/widget/search_box_home/logo/home_white_logo_0ddf152.png"];    });    // group任務都執行完畢,再執行其他操作    dispatch_group_notify(group, dispatch_get_main_queue(), ^{        // 合并圖片        UIGraphicsBeginImageContext(CGSizeMake(300, 300));        [image1 drawInRect:CGRectMake(0, 0, 150, 300)];        [image2 drawInRect:CGRectMake(150, 0, 150, 300)];        UIGraphicsEndImageContext();    });    }-(UIImage *)downloadImageWithUrl:(NSString *)urlStr{    NSURL *url = [NSURL URLWithString:urlStr];    NSData *data = [NSData dataWithContentsOfURL:url];    UIImage *image = [UIImage imageWithData:data];    return image;}

4.定時器

- (void)viewDidLoad{    [super viewDidLoad];    dispatch_source_t timer = dispatch_source_create(DISPATCH_SOURCE_TYPE_TIMER, 0, 0, dispatch_get_main_queue());    dispatch_source_set_timer(timer, DISPATCH_TIME_NOW, 15ull*NSEC_PER_SEC, 1ull*NSEC_PER_SEC);    dispatch_source_set_event_handler(timer, ^{        NSLog(@"wake up");        dispatch_source_cancel(timer);    });    dispatch_source_set_cancel_handler(timer, ^{        NSLog(@"cancel");    });    // 啟動    dispatch_resume(timer);    }

此外,gcd還可監聽文件的讀和寫,信號的中斷等,有興趣的可以進一步鉆研

示例代碼可從Github下載https://github.com/VampireTMAC/GCDdemo


發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
主站蜘蛛池模板: 高雄市| 青阳县| 十堰市| 新平| 兴山县| 新龙县| 邢台市| 绥芬河市| 嵩明县| 逊克县| 金湖县| 石台县| 巴东县| 蚌埠市| 滨州市| 姚安县| 英山县| 长治市| 克拉玛依市| 岳池县| 娄底市| 青浦区| 札达县| 星座| 峨眉山市| 石阡县| 札达县| 富蕴县| 霍山县| 海盐县| 平谷区| 长顺县| 金阳县| 商南县| 奉节县| 阳泉市| 三河市| 中江县| 南丰县| 广州市| 柯坪县|