• 多线程——GCD


     一、 GCD的基本概念

    • GCD:强大的中枢调度,纯C语言,提供了非常多强大的函数。
    • 任务(block):执行什么操作。
    • 队列(queue):用来存放任务。
    • 同步函数dispatch_sync():不创建新线程,在当前线程中顺序执行队列里的任务。
    • 异步函数dispatch_async():创建新线程,在另一条线程中执行队列里的任务。
    • 串行队列:任务一个接着一个有序的执行。
    • 并发队列:让多个任务并发(同时)执行。

     

    二、 队列

    1. GCD中获得串行有2种途径

    (1)使用dispatch_queue_create函数创建串行队列

    (2)使用主队列(跟主线程相关联的队列)

    // 手动创建
    dispatch_queue_t queue = dispatch_queue_create("wendingding", NULL); 
    
    // 获得主线程,主线程就是串行队列
    dispatch_queue_t queue = dispatch_get_main_queue();

    2. 获得并发队列

    (1)使用dispatch_get_global_queue函数获得全局的并发队列

    // 无需手动创建,从中枢调度系统中获取
    ispatch_queue_t dispatch_get_global_queue((DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);

     (2)全局并发队列的优先级

    • #define DISPATCH_QUEUE_PRIORITY_HIGH 2 // 高
    • #define DISPATCH_QUEUE_PRIORITY_DEFAULT 0 // 默认(中)
    • #define DISPATCH_QUEUE_PRIORITY_LOW (-2) // 低
    • #define DISPATCH_QUEUE_PRIORITY_BACKGROUND INT16_MIN // 后台

    三、 GCD的应用

    1. 同步:

     1 - (void)viewDidLoad {
     2     [super viewDidLoad];
     3     // Do any additional setup after loading the view, typically from a nib.
     4     
     5     
     6     // 1. 创建串行队列
     7     dispatch_queue_t sQueue = dispatch_queue_create("sQueue", 0);
     8     
     9     // 2. 把3个任务加入串行队列,同步函数中执行
    10     dispatch_sync(sQueue, ^{
    11         NSLog(@"load1---%@", [NSThread currentThread]);
    12     });
    13     
    14     dispatch_sync(sQueue, ^{
    15         NSLog(@"load2---%@", [NSThread currentThread]);
    16     });
    17     
    18     dispatch_sync(sQueue, ^{
    19         NSLog(@"load3---%@", [NSThread currentThread]);
    20     });
    21     
    22     // 主线程,主线程是在同步函数中执行的
    23     NSLog(@"main---%@", [NSThread mainThread]);
    24     
    25 }

    第一次运行结果:

    2016-10-30 00:11:32.711 06-GCD[20831:12214875] load1---<NSThread: 0x7b74e5a0>{number = 1, name = main}
    2016-10-30 00:11:32.711 06-GCD[20831:12214875] load2---<NSThread: 0x7b74e5a0>{number = 1, name = main}
    2016-10-30 00:11:32.712 06-GCD[20831:12214875] load3---<NSThread: 0x7b74e5a0>{number = 1, name = main}
    2016-10-30 00:11:32.712 06-GCD[20831:12214875] main---<NSThread: 0x7b74e5a0>{number = 1, name = main}

    第二次运行结果:

    2016-10-30 00:15:40.913 06-GCD[20865:12237365] load1---<NSThread: 0x7e202070>{number = 1, name = main}
    2016-10-30 00:15:40.913 06-GCD[20865:12237365] load2---<NSThread: 0x7e202070>{number = 1, name = main}
    2016-10-30 00:15:40.914 06-GCD[20865:12237365] load3---<NSThread: 0x7e202070>{number = 1, name = main}
    2016-10-30 00:15:40.914 06-GCD[20865:12237365] main---<NSThread: 0x7e202070>{number = 1, name = main}

    注解:由以上两次运行结果可知,同步函数不会创建新线程,故以上程序都是在默认线程,即主线程中执行,同步函数内的程序都是按顺序执行的。

    2. 异步:

     1 - (void)viewDidLoad {
     2     [super viewDidLoad];
     3     // Do any additional setup after loading the view, typically from a nib.
     4     
     5     // 1. 获得并发队列
     6     dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
     7     
     8     // 2. 开3个线程,把3个任务加入队列,异步执行
     9     dispatch_async(queue, ^{
    10         NSLog(@"load1---%@", [NSThread currentThread]);
    11     });
    12     
    13     dispatch_async(queue, ^{
    14         NSLog(@"load2---%@", [NSThread currentThread]);
    15     });
    16     
    17     dispatch_async(queue, ^{
    18         NSLog(@"load3---%@", [NSThread currentThread]);
    19     });
    20     
    21     NSLog(@"main---%@", [NSThread mainThread]);
    22     
    23 }

    第一次运行结果:

    2016-10-29 23:52:18.519 06-GCD[20685:12129480] load1---<NSThread: 0x79979100>{number = 3, name = (null)}
    2016-10-29 23:52:18.519 06-GCD[20685:12129482] load2---<NSThread: 0x79676d10>{number = 4, name = (null)}
    2016-10-29 23:52:18.520 06-GCD[20685:12129504] load3---<NSThread: 0x799782d0>{number = 5, name = (null)}
    2016-10-29 23:52:18.519 06-GCD[20685:12129446] main---<NSThread: 0x7996f180>{number = 1, name = main}

    第二次运行结果:

    2016-10-29 23:56:40.791 06-GCD[20734:12158067] main---<NSThread: 0x79f15640>{number = 1, name = main}
    2016-10-29 23:56:40.791 06-GCD[20734:12158259] load3---<NSThread: 0x79f2bc90>{number = 5, name = (null)}
    2016-10-29 23:56:40.791 06-GCD[20734:12158262] load1---<NSThread: 0x7b8284a0>{number = 3, name = (null)}
    2016-10-29 23:56:40.791 06-GCD[20734:12158260] load2---<NSThread: 0x79e247e0>{number = 4, name = (null)}

    第三次运行结果:

    2016-10-29 23:57:12.016 06-GCD[20751:12162437] load1---<NSThread: 0x7b61ead0>{number = 3, name = (null)}
    2016-10-29 23:57:12.016 06-GCD[20751:12162440] load3---<NSThread: 0x7d9113a0>{number = 5, name = (null)}
    2016-10-29 23:57:12.016 06-GCD[20751:12162438] load2---<NSThread: 0x7d822fa0>{number = 4, name = (null)}
    2016-10-29 23:57:12.016 06-GCD[20751:12162185] main---<NSThread: 0x7d809fc0>{number = 1, name = main}

    注解:由运行结果可看出,异步函数会创建出3个新线程,并发队列里的任务不是按照顺序执行的,而是随机并发执行的。

    总结:

    • 并发队列只有放到异步函数里面执行才能得到并发的效果,即放到并发队列里的任务,不按照顺序,随机并发执行的。
    • 并发队列如果放到同步函数里面执行,跟串行队列放到同步函数里面执行的效果是一样的,顺序执行。
    • 同步队列放到异步函数里面执行,则队列里的任务都是顺序执行的。
  • 相关阅读:
    luogu4182 [USACO18JAN] Lifeguards P (单调队列优化dp)
    bzoj3277 串 (后缀数组+二分答案+ST表)
    [模板]后缀数组
    bzoj4361 isn (dp+树状数组+容斥)
    luogu4187 [USACO18JAN]Stamp Painting (dp)
    [USACO15DEC]高低卡(白金)High Card Low Card (Platinum)
    USACO环绕岛屿Surround the Islands 并查集 枚举暴力
    5.7 ~ 5.12 刷题列表
    5.4 ~ 5.6 刷题记录
    HNOI2012 永无乡 无旋Treap
  • 原文地址:https://www.cnblogs.com/gzhu-lkun/p/6010975.html
Copyright © 2020-2023  润新知