iOS GCD常用方法总结

来源:互联网 发布:北大陈晓明 知乎 编辑:程序博客网 时间:2024/05/31 06:22
  1. #pragma mark - Serial Queue  
  2. //在iOS里实现多线程的技术有很多,使用起来最简单的是GCD,执行效率最高的也是GCD,是相对底层的API,都是C的函数。GCD是苹果最推荐的多线程技术,GCD的核心是往dispatch queue里添加要执行的任务,由queue管理任务的执行。  
  3. - (void)Serial:(UIButton *)sender {  
  4.     //dispatch queue有两种:serial queue(串行)和concurrent queue(并行);无论哪种queue都是FIFO  
  5.     //serial queue的特点:执行完queue中第一个任务,执行第二个任务,执行完第二个任务,执行第三个任务,以此类推,任何一个任务的执行,必须等到上个任务执行完毕。  
  6.       
  7. //    //获得serial queue的方式有2种:  
  8. //    //1、获得mainQueue。mainQueue会在主线程中执行,即:主线程中执行队列中的各个任务  
  9. //    dispatch_queue_t mainQueue = dispatch_get_main_queue();  
  10. //    dispatch_async(mainQueue, ^{  
  11. //        NSLog(@"第1个任务,所在线程%@,是否是主线程:%d",[NSThread currentThread],[[NSThread currentThread] isMainThread]);  
  12. //    });//在block里写要执行的任务(代码)  
  13. //    dispatch_async(mainQueue, ^{  
  14. //        NSLog(@"第2个任务,所在线程%@,是否是主线程:%d",[NSThread currentThread],[[NSThread currentThread] isMainThread]);  
  15. //    });//在block里写要执行的任务(代码)  
  16. //    dispatch_async(mainQueue, ^{  
  17. //        NSLog(@"第3个任务,所在线程%@,是否是主线程:%d",[NSThread currentThread],[[NSThread currentThread] isMainThread]);  
  18. //    });//在block里写要执行的任务(代码)  
  19. //    dispatch_async(mainQueue, ^{  
  20. //        NSLog(@"第4个任务,所在线程%@,是否是主线程:%d",[NSThread currentThread],[[NSThread currentThread] isMainThread]);  
  21. //    });//在block里写要执行的任务(代码)  
  22. //    dispatch_async(mainQueue, ^{  
  23. //        NSLog(@"第5个任务,所在线程%@,是否是主线程:%d",[NSThread currentThread],[[NSThread currentThread] isMainThread]);  
  24. //    });//在block里写要执行的任务(代码)  
  25.       
  26.       
  27.     //2、自己创建serial queue。//自己创建的serial queue不会在主线程中执行,queue会开辟一个子线程,在子线程中执行队列中的各个任务  
  28.     dispatch_queue_t mySerialQueue = dispatch_queue_create("com.HMT.GCD.mySerialQueue", DISPATCH_QUEUE_SERIAL);//给queue起名字的时候,苹果推荐使用反向域名格式。  
  29.     dispatch_async(mySerialQueue, ^{  
  30.         NSLog(@"第1个任务,所在线程%@,是否是主线程:%d",[NSThread currentThread],[[NSThread currentThread] isMainThread]);  
  31.     });//在block里写要执行的任务(代码)  
  32.     dispatch_async(mySerialQueue, ^{  
  33.         NSLog(@"第2个任务,所在线程%@,是否是主线程:%d",[NSThread currentThread],[[NSThread currentThread] isMainThread]);  
  34.     });//在block里写要执行的任务(代码)  
  35.     dispatch_async(mySerialQueue, ^{  
  36.         NSLog(@"第3个任务,所在线程%@,是否是主线程:%d",[NSThread currentThread],[[NSThread currentThread] isMainThread]);  
  37.     });//在block里写要执行的任务(代码)  
  38.     dispatch_async(mySerialQueue, ^{  
  39.         NSLog(@"第4个任务,所在线程%@,是否是主线程:%d",[NSThread currentThread],[[NSThread currentThread] isMainThread]);  
  40.     });//在block里写要执行的任务(代码)  
  41.     dispatch_async(mySerialQueue, ^{  
  42.         NSLog(@"第5个任务,所在线程%@,是否是主线程:%d",[NSThread currentThread],[[NSThread currentThread] isMainThread]);  
  43.     });//在block里写要执行的任务(代码)  
  44.       
  45.       
  46. }  
  47.   
  48. #pragma mark - Concurrent Queue  
  49. - (void)Concurrent:(UIButton *)sender {  
  50.     //concurrent(并行)queue是另外一种队列。其特点:队列中的任务,第一个先执行,不等第一个执行完毕,第二个就开始执行了,不等第二个任务执行完毕,第三个就开始执行了,以此类推。后面的任务执行的晚,但是不会等前面的执行完才执行。  
  51.       
  52. //    //获得concurrent queue的方法有2种:  
  53. //    //1、获得global queue。  
  54. //    dispatch_queue_t globalQueue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);//第一个参数控制globalQueue的优先级,一共有4个优先级DISPATCH_QUEUE_PRIORITY_HIGH、DISPATCH_QUEUE_PRIORITY_DEFAULT、DISPATCH_QUEUE_PRIORITY_LOW、DISPATCH_QUEUE_PRIORITY_BACKGROUND。第二个参数是苹果预留参数,未来会用,目前填写为0.  
  55. //    //global queue会根据需要开辟若干个线程,并行执行队列中的任务(开始较晚的任务未必最后结束,开始较早的任务未必最先完成),开辟的线程数量取决于多方面因素,比如:任务的数量,系统的内存资源等等,会以最优的方式开辟线程---根据需要开辟适当的线程。  
  56. //    dispatch_async(globalQueue, ^{  
  57. //        NSLog(@"第1个任务,所在线程%@,是否是主线程:%d",[NSThread currentThread],[[NSThread currentThread] isMainThread]);  
  58. //    });//在block里写要执行的任务(代码)  
  59. //    dispatch_async(globalQueue, ^{  
  60. //        NSLog(@"第2个任务,所在线程%@,是否是主线程:%d",[NSThread currentThread],[[NSThread currentThread] isMainThread]);  
  61. //    });//在block里写要执行的任务(代码)  
  62. //    dispatch_async(globalQueue, ^{  
  63. //        NSLog(@"第3个任务,所在线程%@,是否是主线程:%d",[NSThread currentThread],[[NSThread currentThread] isMainThread]);  
  64. //    });//在block里写要执行的任务(代码)  
  65. //    dispatch_async(globalQueue, ^{  
  66. //        NSLog(@"第4个任务,所在线程%@,是否是主线程:%d",[NSThread currentThread],[[NSThread currentThread] isMainThread]);  
  67. //    });//在block里写要执行的任务(代码)  
  68. //    dispatch_async(globalQueue, ^{  
  69. //        NSLog(@"第5个任务,所在线程%@,是否是主线程:%d",[NSThread currentThread],[[NSThread currentThread] isMainThread]);  
  70. //    });//在block里写要执行的任务(代码)  
  71. //    dispatch_async(globalQueue, ^{  
  72. //        NSLog(@"第6个任务,所在线程%@,是否是主线程:%d",[NSThread currentThread],[[NSThread currentThread] isMainThread]);  
  73. //    });//在block里写要执行的任务(代码)  
  74. //    dispatch_async(globalQueue, ^{  
  75. //        NSLog(@"第7个任务,所在线程%@,是否是主线程:%d",[NSThread currentThread],[[NSThread currentThread] isMainThread]);  
  76. //    });//在block里写要执行的任务(代码)  
  77. //    dispatch_async(globalQueue, ^{  
  78. //        NSLog(@"第8个任务,所在线程%@,是否是主线程:%d",[NSThread currentThread],[[NSThread currentThread] isMainThread]);  
  79. //    });//在block里写要执行的任务(代码)  
  80. //    dispatch_async(globalQueue, ^{  
  81. //        NSLog(@"第9个任务,所在线程%@,是否是主线程:%d",[NSThread currentThread],[[NSThread currentThread] isMainThread]);  
  82. //    });//在block里写要执行的任务(代码)  
  83. //    dispatch_async(globalQueue, ^{  
  84. //        NSLog(@"第10个任务,所在线程%@,是否是主线程:%d",[NSThread currentThread],[[NSThread currentThread] isMainThread]);  
  85. //    });//在block里写要执行的任务(代码)  
  86.       
  87.       
  88.       
  89.     //2、自己创建concurrent queue。  
  90.     //自己创建的concurrent queue会根据需要开辟若干个线程,并行执行队列中的任务(开始较晚的任务未必最后结束,开始较早的任务未必最先完成),开辟的线程数量取决于多方面因素,比如:任务的数量,系统的内存资源等等,会以最优的方式开辟线程---根据需要开辟适当的线程。  
  91.     dispatch_queue_t myConcurrentQueue = dispatch_queue_create("com.HMT.GCD.myConcurrentQueue", DISPATCH_QUEUE_CONCURRENT);  
  92.     dispatch_async(myConcurrentQueue, ^{  
  93.         NSLog(@"第1个任务,所在线程%@,是否是主线程:%d",[NSThread currentThread],[[NSThread currentThread] isMainThread]);  
  94.     });//在block里写要执行的任务(代码)  
  95.     dispatch_async(myConcurrentQueue, ^{  
  96.         NSLog(@"第2个任务,所在线程%@,是否是主线程:%d",[NSThread currentThread],[[NSThread currentThread] isMainThread]);  
  97.     });//在block里写要执行的任务(代码)  
  98.     dispatch_async(myConcurrentQueue, ^{  
  99.         NSLog(@"第3个任务,所在线程%@,是否是主线程:%d",[NSThread currentThread],[[NSThread currentThread] isMainThread]);  
  100.     });//在block里写要执行的任务(代码)  
  101.     dispatch_async(myConcurrentQueue, ^{  
  102.         NSLog(@"第4个任务,所在线程%@,是否是主线程:%d",[NSThread currentThread],[[NSThread currentThread] isMainThread]);  
  103.     });//在block里写要执行的任务(代码)  
  104.     dispatch_async(myConcurrentQueue, ^{  
  105.         NSLog(@"第5个任务,所在线程%@,是否是主线程:%d",[NSThread currentThread],[[NSThread currentThread] isMainThread]);  
  106.     });//在block里写要执行的任务(代码)  
  107.     dispatch_async(myConcurrentQueue, ^{  
  108.         NSLog(@"第6个任务,所在线程%@,是否是主线程:%d",[NSThread currentThread],[[NSThread currentThread] isMainThread]);  
  109.     });//在block里写要执行的任务(代码)  
  110.     dispatch_async(myConcurrentQueue, ^{  
  111.         NSLog(@"第7个任务,所在线程%@,是否是主线程:%d",[NSThread currentThread],[[NSThread currentThread] isMainThread]);  
  112.     });//在block里写要执行的任务(代码)  
  113.     dispatch_async(myConcurrentQueue, ^{  
  114.         NSLog(@"第8个任务,所在线程%@,是否是主线程:%d",[NSThread currentThread],[[NSThread currentThread] isMainThread]);  
  115.     });//在block里写要执行的任务(代码)  
  116.     dispatch_async(myConcurrentQueue, ^{  
  117.         NSLog(@"第9个任务,所在线程%@,是否是主线程:%d",[NSThread currentThread],[[NSThread currentThread] isMainThread]);  
  118.     });//在block里写要执行的任务(代码)  
  119.     dispatch_async(myConcurrentQueue, ^{  
  120.         NSLog(@"第10个任务,所在线程%@,是否是主线程:%d",[NSThread currentThread],[[NSThread currentThread] isMainThread]);  
  121.     });//在block里写要执行的任务(代码)  
  122. }  
  123.   
  124. #pragma mark - 延迟3秒  
  125. - (void)after:(UIButton *)sender {  
  126.     double delayInSeconds = 3.0;  
  127.     dispatch_time_t popTime = dispatch_time(DISPATCH_TIME_NOW, (int64_t)(delayInSeconds * NSEC_PER_SEC));  
  128.       
  129. //    dispatch_after(popTime, dispatch_get_main_queue(), ^(void){  
  130. //        NSLog(@"Hello");  
  131. //    });//dispatch_after函数是延迟执行某个任务,任务既可以在mainQueue中进行也可以在其他queue中进行.既可以在serial队列里执行也可以在concurrent队列里执行。  
  132.       
  133.     dispatch_queue_t myConcurrentQueue = dispatch_queue_create("com.HMT.GCD.myConcurrentQueue", DISPATCH_QUEUE_CONCURRENT);  
  134.     dispatch_after(popTime, myConcurrentQueue, ^(void){  
  135.         NSLog(@"world");  
  136.     });  
  137. }  
  138.   
  139. #pragma mark - 若干任务执行完之后,想要执行某个任务  
  140. - (void)group:(UIButton *)sender {  
  141.     dispatch_group_t group = dispatch_group_create();  
  142.     dispatch_queue_t myConcurrentQueue = dispatch_queue_create("com.HMT.GCD.myConcurrentQueue", DISPATCH_QUEUE_CONCURRENT);  
  143.       
  144.     //dispatch_group_async用于把不同的任务归为一组  
  145.     //dispatch_group_notify当指定组的任务执行完毕之后,执行给定的任务  
  146.     dispatch_group_async(group, myConcurrentQueue, ^{  
  147.         NSLog(@"第1个任务,所在线程%@,是否是主线程:%d",[NSThread currentThread],[[NSThread currentThread] isMainThread]);  
  148.     });  
  149.     dispatch_group_async(group, myConcurrentQueue, ^{  
  150.         NSLog(@"第2个任务,所在线程%@,是否是主线程:%d",[NSThread currentThread],[[NSThread currentThread] isMainThread]);  
  151.     });  
  152.     dispatch_group_async(group, myConcurrentQueue, ^{  
  153.         NSLog(@"第3个任务,所在线程%@,是否是主线程:%d",[NSThread currentThread],[[NSThread currentThread] isMainThread]);  
  154.     });  
  155.     dispatch_group_async(group, myConcurrentQueue, ^{  
  156.         NSLog(@"第4个任务,所在线程%@,是否是主线程:%d",[NSThread currentThread],[[NSThread currentThread] isMainThread]);  
  157.     });  
  158.     dispatch_group_notify(group, myConcurrentQueue, ^{  
  159.         NSLog(@"group中的任务都执行完毕之后,执行此任务。所在线程%@,是否是主线程:%d",[NSThread currentThread],[[NSThread currentThread] isMainThread]);  
  160.     });  
  161.     dispatch_group_async(group, myConcurrentQueue, ^{  
  162.         NSLog(@"第5个任务,所在线程%@,是否是主线程:%d",[NSThread currentThread],[[NSThread currentThread] isMainThread]);  
  163.     });  
  164.     dispatch_group_async(group, myConcurrentQueue, ^{  
  165.         NSLog(@"第6个任务,所在线程%@,是否是主线程:%d",[NSThread currentThread],[[NSThread currentThread] isMainThread]);  
  166.     });  
  167.       
  168. }  
  169.   
  170. #pragma mark - barrier  
  171. - (void)barrier:(UIButton *)sender {  
  172.     //为了保证访问同一个数据时,数据的安全,我们可以使用serial queue解决数据安全访问的问题。  
  173.     //serial queue的缺陷是:后面的任务 必须等待 前面的任务 执行完毕 才能执行  
  174.     //对于往数据库写入数据 使用serial queue无疑能保证数据的安全。  
  175.     //对于从数据库中读取数据,使用serial queue就不太合适了,效率比较低。使用concurrent queue无疑是最合适的。  
  176.     //真实的项目中,通常既有对数据库的写入,又有数据库的读取。如何处理才最合适呢?  
  177.       
  178.     //下面给出了 既有数据库数据读取,又有数据库数据写入的处理方法dispatch_barrier_async  
  179.     dispatch_queue_t myConcurrentQueue = dispatch_queue_create("com.HMT.GCD.myConcurrentQueue", DISPATCH_QUEUE_CONCURRENT);  
  180.     dispatch_async(myConcurrentQueue, ^{  
  181.         NSLog(@"读取一些数据,所在线程%@,是否是主线程:%d",[NSThread currentThread],[[NSThread currentThread] isMainThread]);  
  182.     });  
  183.     dispatch_async(myConcurrentQueue, ^{  
  184.         NSLog(@"读取另外一些数据,所在线程%@,是否是主线程:%d",[NSThread currentThread],[[NSThread currentThread] isMainThread]);  
  185.     });  
  186.     dispatch_async(myConcurrentQueue, ^{  
  187.         NSLog(@"读取这些数据,所在线程%@,是否是主线程:%d",[NSThread currentThread],[[NSThread currentThread] isMainThread]);  
  188.     });  
  189.     dispatch_async(myConcurrentQueue, ^{  
  190.         NSLog(@"读取那些数据,所在线程%@,是否是主线程:%d",[NSThread currentThread],[[NSThread currentThread] isMainThread]);  
  191.     });  
  192.       
  193.       
  194.       
  195.     dispatch_barrier_async(myConcurrentQueue, ^{  
  196.         NSLog(@"写入某些数据,所在线程%@,是否是主线程:%d",[NSThread currentThread],[[NSThread currentThread] isMainThread]);  
  197.     });//dispatch_barrier_async就像一道墙,之前的任务都并行执行,执行完毕之后,执行barrier中的任务,之后的任务也是并行执行。  
  198.       
  199.       
  200.       
  201.     dispatch_async(myConcurrentQueue, ^{  
  202.         NSLog(@"读取XXX数据,所在线程%@,是否是主线程:%d",[NSThread currentThread],[[NSThread currentThread] isMainThread]);  
  203.     });  
  204.     dispatch_async(myConcurrentQueue, ^{  
  205.         NSLog(@"读取OOXX数据,所在线程%@,是否是主线程:%d",[NSThread currentThread],[[NSThread currentThread] isMainThread]);  
  206.     });  
  207.     dispatch_async(myConcurrentQueue, ^{  
  208.         NSLog(@"读取aaa数据,所在线程%@,是否是主线程:%d",[NSThread currentThread],[[NSThread currentThread] isMainThread]);  
  209.     });  
  210.     dispatch_async(myConcurrentQueue, ^{  
  211.         NSLog(@"读取bbb数据,所在线程%@,是否是主线程:%d",[NSThread currentThread],[[NSThread currentThread] isMainThread]);  
  212.     });  
  213. }  
  214.   
  215. #pragma mark - 重复执行某任务  
  216. - (void)apply:(UIButton *)sender {  
  217.     //GCD中提供了API让某个任务执行若干次。  
  218.     NSArray *array = [NSArray arrayWithObjects:@"红楼梦",@"水浒传",@"三国演义",@"西游记", nil nil];  
  219.   
  220.     dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);  
  221.     dispatch_apply([array count], queue, ^(size_t index) {  
  222.         NSLog(@"%@所在线程%@,是否是主线程:%d",[array objectAtIndex:index],[NSThread currentThread],[[NSThread currentThread] isMainThread]);  
  223.     });  
  224. }  
  225.   
  226. #pragma mark - once  
  227. - (void)once:(UIButton *)sender {  
  228.     //dispatch_once 用于定义那些只需要执行一次的代码,比如单例的创建  
  229.     static dispatch_once_t onceToken;  
  230.     dispatch_once(&onceToken, ^{  
  231.         NSLog(@"只执行一次");  
  232.         //这个block里的代码,在程序执行过程中只会执行一次。  
  233.         //比如在这里些单例的初始化  
  234. //        static YourClass *instance = nil;  
  235. //        instance = [[YourClass alloc] init];  
  236.     });  
  237. }  
  238.   
  239. #pragma mark - 同步  
  240. - (void)syn:(id)sender {  
  241.     //我们一直在用  dispatch_async,GCD里有一些API是dispatch_sync,二者有什么区别呢?  
  242.     //dispatch_async无需等block执行完,继续执行dispatch_async后面的代码  
  243.     //dispatch_sync必须等block执行完,才继续执行dispatch_sync后面的代码  
  244.     dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);  
  245. //  
  246. //    dispatch_sync(queue, ^{  
  247. //        for (int i = 0; i < 10; i++) {  
  248. //            NSLog(@"%d",i);  
  249. //        }  
  250. //    });  
  251. //    NSLog(@"haha");  
  252.       
  253.       
  254.     dispatch_async(queue, ^{  
  255.         for (int i = 0; i < 10; i++) {  
  256.             NSLog(@"%d",i);  
  257.         }  
  258.     });  
  259.     NSLog(@"haha");  
  260. }  
  261.   
  262. #pragma mark - GCD函数指针  
  263. - (void)functionPoint:(id)sender {  
  264.       
  265.     //dispatch_async_f往队列里放函数指针,队列控制相应函数的执行,不在是控制block的执行  
  266.     dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);  
  267.     dispatch_async_f(queue, @"你好", function);//函数指针对应的函数类型:必须没有返回值,参数必须是void *。函数指针对应的参数,由dispatch_async_f第二个参数提供,可以是任意对象类型。  
  268. }  
  269.   
  270. void function(voidvoid *context)  
  271. {  
  272.     NSLog(@"%@ 所在线程%@,是否是主线程:%d",context,[NSThread currentThread],[[NSThread currentThread] isMainThread]);  
  273. }
0 0
原创粉丝点击