标签:style   class   blog   code   http   ext   
 iOS开发多线程网络———多线程概念及GCD
一.多线程的概念
1.什么是进程? 
     a.正在进行中的程序被称为进程,负责程序运行的内存分配
     b.每一个进程都有自己独立的虚拟内存空间 
2.什么是线程?
     a.线程是进程中一个独立的执行路径(控制单元)
     b.一个进程中至少包含一条线程,即主线程
      (在iOS中主线程在栈区中区区只占1M,而子线程只有512k) 
     c. 线程可以将耗时的执行路径(如:网络请求)放在其他线程中执行被称为子线程
      (注意:子线程运行完毕被主线程回收了,是杀不掉的,但是可以暂停或休眠)
     d.创建线程的目的就是为了开启一条新的执行路径,运行指定的代码,与主线程中的代码实现同时运行 
        就是为了在一个CPU上实现快速切换! 
3.多任务系统调度 
          当运行多个程序时,每个应用程序都是由操作系统分配短暂的时间片(Timeslice)轮流使用CPU,由于 CPU对每个
      时间片的处理速度非常快(以微秒来计算的),因此用户看起来好像这些任务在同时执行的,但是在任意一个时刻点上,
      CPU只会处理一个任务
4.使用多线程的利弊 
       当了解了多线程的概念之后,我们来看看有多线程都有哪些优势和弊端
      A.优势 
          a.充分发挥多核处理优势,将不同线程任务分配给不同的处理器,真正进入"并行运算"状态
          b.将耗时的任务分配到其他线程执行,由主线程负责统一更新界面回使应用程序更加流畅,用户体验更好
          c.当硬件处理器的数量增加,程序会运行更快,而程序无需做任何调整
     B.弊端
          新建线程会消耗内存空间和CPU时间,线程太多会降低系统的运行性能
     C.误区
         多线程技术是为了并发执行多项任务,不会提高单个算法本身的执行效率 (并发:指两个或多个任务在同一时间间隔内发生)
 
iOS多线程技术有三种,分别是: GCD 、NSThread 、NSOperation/NSOperationQueue
  
 二.GCD
1.什么是GCD
       GCD为Grand Central Dispatch的缩写,简单的说就是是Apple在iOS4.0开发的一个多核编程较新的解决方法,用来优化应
     用程序以支持多核处理器。它是基于C语言的底层API,用Block定义任务,使用起来非常灵活便捷,提供了更多的控制能力以及操作
     队列中所不能使用的底层函数 
2.GCD的核心思想 
   (1) GCD 的核心思想就是将操作放到队列中去执行
           a.操作使用Blocks定义
           b.队列负责调度热舞执行所在的线程以及具体的执行时间
           c.队列的特点是先进先出(FIFO)的,新添加队列的操作都会排在队尾
   (2)提示:GCD的函数都是以dispatch(分派、调度)开头的
   (3)队列 (dispatch_queue_t)
           a. 串行队列:队列中的任务只会顺序执行
           b. 并行队列:队列中的任务通常会并发执行
          (注意:队列不是线程,也不表示对应的CPU  队列就是负责调度!谁空闲,就把任务给谁!) 
   (4)操作
           a.dispatch_async 异步操作,会并发执行,无法确定任务的执行顺序
           b.dispatch_sync   同步操作,会依次顺序执行,能够决定任务的执行顺序 
     2.1 串行队列:队列中的任务只会顺序执行
      串行队列的同步和异步任务代码演示:
  1 #import "LDViewController.h"
 2 
 3 @interface LDViewController ()
 4 
 5 @end
 6 
 7 @implementation LDViewController
 8 
 9 - (void)viewDidLoad
10 {
11     [super viewDidLoad];
12     
13     NSLog(@"%@",[NSThread currentThread]);
14     
15     [self gcdDemo1];
16 }
17 
18 #pragma mark - GCD方法
19 #pragma mark - 串行(一个接一个,排队跑步,保持队形)队列
20 - (void)gcdDemo1
21 {
22     //将操作放在队列中
23     //在C语言函数中,定义类型,绝大多数的结尾是_t 或者ref
24     //使用串行队列的异步任务非常有用!新建子线程是有开销的,不能无休止新建线程
25     //即可以保证效率 (新建一个子线程) , 又能够实现并发
26     
27     //应用案例
28     
29     //1>从网络上下载图片
30     //2>滤镜(高光,红眼……)
31     
32     dispatch_queue_t LD = dispatch_queue_create("liudeng", DISPATCH_QUEUE_SERIAL);
33 
34     
35     //串行队列的同步任务,同样会在主线程上运行
36     
37     for (int i = 0 ; i < 6; ++i) {
38         //同步任务:顺序执行
39         dispatch_sync(LD, ^{
40             NSLog(@"%@ %d", [NSThread currentThread],i);
41         });
42     }
43     
44     for (int i = 0; i < 7; ++i) {
45         //异步任务 :并发执行,但是如果在串行队列中,仍然会依次顺序执行
46         dispatch_async(LD, ^{
47             //[NSThread currentThread]  可以在开发中,跟踪当前线程
48             //num = 1, 表示主线程
49             //num = 2, 表示第2个子线程……
50             NSLog(@"%@ %d",[NSThread currentThread], i);
51         });
52     }
53     
54 }
55 
56 
57 @end
 
     运行结果及总结:
       a.在串行队列中,分别运行同步任务和异步任务时,结果都为下面有序结果 (可以看出异步任务在串行队列中也是有顺序的)
2014-06-14 00:07:31.337 GCD演练[1346:60b] <NSThread: 0x10941c500>{name = (null), num = 1}
2014-06-14 00:07:31.339 GCD演练[1346:1303] <NSThread: 0x1093045e0>{name = (null), num = 2} 0
2014-06-14 00:07:31.340 GCD演练[1346:1303] <NSThread: 0x1093045e0>{name = (null), num = 2} 1
2014-06-14 00:07:31.341 GCD演练[1346:1303] <NSThread: 0x1093045e0>{name = (null), num = 2} 2
2014-06-14 00:07:31.341 GCD演练[1346:1303] <NSThread: 0x1093045e0>{name = (null), num = 2} 3
2014-06-14 00:07:31.342 GCD演练[1346:1303] <NSThread: 0x1093045e0>{name = (null), num = 2} 4
2014-06-14 00:07:31.342 GCD演练[1346:1303] <NSThread: 0x1093045e0>{name = (null), num = 2} 5
       b.在串行队列中,同步任务在上,异步任务在下
 1 2014-06-14 00:25:38.240 GCD演练[1432:60b] <NSThread: 0x109506690>{name = (null), num = 1}
 2 2014-06-14 00:25:38.242 GCD演练[1432:60b] <NSThread: 0x109506690>{name = (null), num = 1} 0
 3 2014-06-14 00:25:38.242 GCD演练[1432:60b] <NSThread: 0x109506690>{name = (null), num = 1} 1
 4 2014-06-14 00:25:38.243 GCD演练[1432:60b] <NSThread: 0x109506690>{name = (null), num = 1} 2
 5 2014-06-14 00:25:38.243 GCD演练[1432:60b] <NSThread: 0x109506690>{name = (null), num = 1} 3
 6 2014-06-14 00:25:38.244 GCD演练[1432:60b] <NSThread: 0x109506690>{name = (null), num = 1} 4
 7 2014-06-14 00:25:38.244 GCD演练[1432:60b] <NSThread: 0x109506690>{name = (null), num = 1} 5
 8 2014-06-14 00:25:38.245 GCD演练[1432:60b] <NSThread: 0x109506690>{name = (null), num = 1} 6
 9 2014-06-14 00:25:38.245 GCD演练[1432:1303] <NSThread: 0x1092799e0>{name = (null), num = 2} 0
10 2014-06-14 00:25:38.246 GCD演练[1432:1303] <NSThread: 0x1092799e0>{name = (null), num = 2} 1
11 2014-06-14 00:25:38.246 GCD演练[1432:1303] <NSThread: 0x1092799e0>{name = (null), num = 2} 2
12 2014-06-14 00:25:38.247 GCD演练[1432:1303] <NSThread: 0x1092799e0>{name = (null), num = 2} 3
13 2014-06-14 00:25:38.248 GCD演练[1432:1303] <NSThread: 0x1092799e0>{name = (null), num = 2} 4
14 2014-06-14 00:25:38.258 GCD演练[1432:1303] <NSThread: 0x1092799e0>{name = (null), num = 2} 5
        c.在串行队列中,异步任务在上,同步任务在下 (可以看出队列的特点是先进先出(FIFO)的,新添加队列的操作都会排在队尾)
 1 2014-06-14 00:23:43.751 GCD演练[1414:60b] <NSThread: 0x10931c500>{name = (null), num = 1}
 2 2014-06-14 00:23:43.753 GCD演练[1414:1303] <NSThread: 0x1092694a0>{name = (null), num = 2} 0
 3 2014-06-14 00:23:43.753 GCD演练[1414:1303] <NSThread: 0x1092694a0>{name = (null), num = 2} 1
 4 2014-06-14 00:23:43.754 GCD演练[1414:1303] <NSThread: 0x1092694a0>{name = (null), num = 2} 2
 5 2014-06-14 00:23:43.754 GCD演练[1414:1303] <NSThread: 0x1092694a0>{name = (null), num = 2} 3
 6 2014-06-14 00:23:43.755 GCD演练[1414:1303] <NSThread: 0x1092694a0>{name = (null), num = 2} 4
 7 2014-06-14 00:23:43.755 GCD演练[1414:1303] <NSThread: 0x1092694a0>{name = (null), num = 2} 5
 8 2014-06-14 00:23:43.756 GCD演练[1414:1303] <NSThread: 0x1092694a0>{name = (null), num = 2} 6
 9 2014-06-14 00:23:43.756 GCD演练[1414:60b] <NSThread: 0x10931c500>{name = (null), num = 1} 0
10 2014-06-14 00:23:43.757 GCD演练[1414:60b] <NSThread: 0x10931c500>{name = (null), num = 1} 1
11 2014-06-14 00:23:43.757 GCD演练[1414:60b] <NSThread: 0x10931c500>{name = (null), num = 1} 2
12 2014-06-14 00:23:43.758 GCD演练[1414:60b] <NSThread: 0x10931c500>{name = (null), num = 1} 3
13 2014-06-14 00:23:43.758 GCD演练[1414:60b] <NSThread: 0x10931c500>{name = (null), num = 1} 4
14 2014-06-14 00:23:43.760 GCD演练[1414:60b] <NSThread: 0x10931c500>{name = (null), num = 1} 5
     2.2 并行队列:队列中的任务通常会并发执行 
     并行队列的同步和异步任务代码演示:
 1 #import "LDViewController.h"
 2 
 3 @interface LDViewController ()
 4 
 5 @end
 6 
 7 @implementation LDViewController
 8 
 9 - (void)viewDidLoad
10 {
11     [super viewDidLoad];
12     
13     NSLog(@"%@",[NSThread currentThread]);
14     
15     [self gcdDemo2];
16 }
17 
18 #pragma mark - GCD方法
19 
20 #pragma mark - 并行 (并排跑,类似于赛跑)
21 - (void)gcdDemo2
22 {
23     //特点:没有队形,执行顺序程序员不能控制
24     //应用场景:并发执行任务,没有先后顺序
25     //并行队列容易出错!并行队列不能控制新建线程的数量!
26     dispatch_queue_t LD = dispatch_queue_create("liudeng", DISPATCH_QUEUE_CONCURRENT);
27 
28     for (int i = 0 ; i < 7; ++i) {
29         //同步任务:顺序执行
30         dispatch_sync(LD, ^{
31             NSLog(@"%@ %d", [NSThread currentThread],i);
32         });
33     }
34 
35     for (int i = 0; i < 6; ++i) {
36         //异步任务
37         dispatch_async(LD, ^{
38             //[NSThread currentThread]  可以在开发中,跟踪当前线程
39             //num = 1, 表示主线程
40             //num = 2, 表示第2个子线程……
41             NSLog(@"%@ %d",[NSThread currentThread], i);
42         });
43     }
44 }
    运行结果及总结:
       a.在并行队列中,单独运行同步任务结果 (可以看出同步任务在并行队列中是有顺序的)
1 2014-06-14 00:42:54.172 GCD演练[1503:60b] <NSThread: 0x10921c630>{name = (null), num = 1}
2 2014-06-14 00:42:54.174 GCD演练[1503:60b] <NSThread: 0x10921c630>{name = (null), num = 1} 0
3 2014-06-14 00:42:54.175 GCD演练[1503:60b] <NSThread: 0x10921c630>{name = (null), num = 1} 1
4 2014-06-14 00:42:54.175 GCD演练[1503:60b] <NSThread: 0x10921c630>{name = (null), num = 1} 2
5 2014-06-14 00:42:54.176 GCD演练[1503:60b] <NSThread: 0x10921c630>{name = (null), num = 1} 3
6 2014-06-14 00:42:54.176 GCD演练[1503:60b] <NSThread: 0x10921c630>{name = (null), num = 1} 4
7 2014-06-14 00:42:54.177 GCD演练[1503:60b] <NSThread: 0x10921c630>{name = (null), num = 1} 5
       b.在并行队列中,单独运行异步任务结果 (可以看出异步任务在并行队列中是没有顺序的)
1 2014-06-14 00:45:51.925 GCD演练[1522:60b] <NSThread: 0x10930f2c0>{name = (null), num = 1}
2 2014-06-14 00:45:51.927 GCD演练[1522:3007] <NSThread: 0x109229b90>{name = (null), num = 5} 1
3 2014-06-14 00:45:51.927 GCD演练[1522:3503] <NSThread: 0x1092081c0>{name = (null), num = 3} 2
4 2014-06-14 00:45:51.927 GCD演练[1522:3603] <NSThread: 0x109420830>{name = (null), num = 4} 3
5 2014-06-14 00:45:51.927 GCD演练[1522:1303] <NSThread: 0x10921c760>{name = (null), num = 2} 0
6 2014-06-14 00:45:51.928 GCD演练[1522:3007] <NSThread: 0x109229b90>{name = (null), num = 5} 4
7 2014-06-14 00:45:51.930 GCD演练[1522:3603] <NSThread: 0x109420830>{name = (null), num = 4} 6
       c.在并行队列中,同步任务在上,异步任务在下结果  (同步任务是有序的,而且还是在主线程上执行,只有同步任务执行完毕之后,异步任务才开始工作)
 1 2014-06-14 00:48:50.231 GCD演练[1541:60b] <NSThread: 0x10931c500>{name = (null), num = 1}
 2 2014-06-14 00:48:50.232 GCD演练[1541:60b] <NSThread: 0x10931c500>{name = (null), num = 1} 0
 3 2014-06-14 00:48:50.233 GCD演练[1541:60b] <NSThread: 0x10931c500>{name = (null), num = 1} 1
 4 2014-06-14 00:48:50.233 GCD演练[1541:60b] <NSThread: 0x10931c500>{name = (null), num = 1} 2
 5 2014-06-14 00:48:50.234 GCD演练[1541:60b] <NSThread: 0x10931c500>{name = (null), num = 1} 3
 6 2014-06-14 00:48:50.234 GCD演练[1541:60b] <NSThread: 0x10931c500>{name = (null), num = 1} 4
 7 2014-06-14 00:48:50.235 GCD演练[1541:60b] <NSThread: 0x10931c500>{name = (null), num = 1} 5
 8 2014-06-14 00:48:50.235 GCD演练[1541:60b] <NSThread: 0x10931c500>{name = (null), num = 1} 6
 9 2014-06-14 00:48:50.236 GCD演练[1541:1303] <NSThread: 0x1092205c0>{name = (null), num = 2} 0
10 2014-06-14 00:48:50.236 GCD演练[1541:3603] <NSThread: 0x109220730>{name = (null), num = 3} 3
11 2014-06-14 00:48:50.236 GCD演练[1541:3403] <NSThread: 0x10934e550>{name = (null), num = 5} 1
12 2014-06-14 00:48:50.236 GCD演练[1541:3503] <NSThread: 0x10934cc40>{name = (null), num = 4} 2
13 2014-06-14 00:48:50.237 GCD演练[1541:1303] <NSThread: 0x1092205c0>{name = (null), num = 2} 4
14 2014-06-14 00:48:50.237 GCD演练[1541:3403] <NSThread: 0x10934e550>{name = (null), num = 5} 6
       d.在并行队列中,异步任务在上,同步任务在下结果  (没有队行,执行顺序程序员不能控制)
 1 2014-06-14 00:54:38.679 GCD演练[1559:60b] <NSThread: 0x10960f2c0>{name = (null), num = 1}
 2 2014-06-14 00:54:38.680 GCD演练[1559:60b] <NSThread: 0x10960f2c0>{name = (null), num = 1} 0
 3 2014-06-14 00:54:38.681 GCD演练[1559:1303] <NSThread: 0x10937c290>{name = (null), num = 2} 0
 4 2014-06-14 00:54:38.681 GCD演练[1559:3503] <NSThread: 0x109623b30>{name = (null), num = 4} 2
 5 2014-06-14 00:54:38.681 GCD演练[1559:3403] <NSThread: 0x10cf04e00>{name = (null), num = 3} 1
 6 2014-06-14 00:54:38.681 GCD演练[1559:3603] <NSThread: 0x10cf07580>{name = (null), num = 5} 3
 7 2014-06-14 00:54:38.681 GCD演练[1559:60b] <NSThread: 0x10960f2c0>{name = (null), num = 1} 1
 8 2014-06-14 00:54:38.684 GCD演练[1559:60b] <NSThread: 0x10960f2c0>{name = (null), num = 1} 2
 9 2014-06-14 00:54:38.684 GCD演练[1559:3403] <NSThread: 0x10cf04e00>{name = (null), num = 3} 6
10 2014-06-14 00:54:38.681 GCD演练[1559:3503] <NSThread: 0x109623b30>{name = (null), num = 4} 5
11 2014-06-14 00:54:38.685 GCD演练[1559:60b] <NSThread: 0x10960f2c0>{name = (null), num = 1} 3
12 2014-06-14 00:54:38.681 GCD演练[1559:1303] <NSThread: 0x10937c290>{name = (null), num = 2} 4
13 2014-06-14 00:54:38.685 GCD演练[1559:60b] <NSThread: 0x10960f2c0>{name = (null), num = 1} 4
14 2014-06-14 00:54:38.685 GCD演练[1559:60b] <NSThread: 0x10960f2c0>{name = (null), num = 1} 5
      2.3 全局队列:全局队列是系统的,直接通过(get)拿过来用就可以了
 1 #pragma mark - GCD方法
 2 
 3 #pragma mark - 全局队列 (苹果为了方便多线程的设计,提供一个全局队列,供所有的APP共同使用)
 4 - (void)gcdDemo3
 5 {
 6     dispatch_queue_t LD = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
 7     for (int i = 0 ; i < 7; ++i) {
 8         //同步任务:顺序执行
 9         dispatch_sync(LD, ^{
10             NSLog(@"%@ %d", [NSThread currentThread],i);
11         });
12     }
13     
14     for (int i = 0; i < 7; ++i) {
15         //异步任务 :并发执行,但是如果在串行队列中,仍然会依次顺序执行
16         dispatch_async(LD, ^{
17             //[NSThread currentThread]  可以在开发中,跟踪当前线程
18             //num = 1, 表示主线程
19             //num = 2, 表示第2个子线程……
20             NSLog(@"%@ %d",[NSThread currentThread], i);
21         });
22     }
     全局队列和并行队列很类似,比较如下:
             a.全局队列不需要创建,直接get就能用 
             b.两个队列的执行效果相同
             c.全局队列没有名称,调试时,无法确认准确队列
       2.4 主(线程)队列:
 1 #pragma mark - 主(线程)队列,保证操作在主线程上执行
 2 - (void)gcdDemo4
 3 {
 4     //每一个应用程序都只有一个主线程
 5     //为什么需要在主线程上工作?
 6     //在IOS开发中,所有UI的更新工作,都必须在主线程上执行!
 7     dispatch_queue_t LD = dispatch_get_main_queue();
 8     //主线程是一直工作的,除非将程序杀掉,否则主线程的工作永远不会结束
 9     //同步任务,主线程会阻塞
10 //    dispatch_sync(LD, ^{
11 //        NSLog(@"你好");
12 //    });
13     
14     for (int i = 0; i < 6; ++i) {
15         //异步任务,在主线程上运行,同时是保持队形的
16         dispatch_async(LD, ^{
17             NSLog(@"%@  %d", [NSThread currentThread], i);
18         });
19     }
      
3.GCD小结: 
            串行队列,同步任务,不需要新建线程
            串行队列,异步任务,需要一个子线程,线程的创建和回收不需要程序员参与! “是最安全的一种选择,串行队列是get不到的,只能创建”
            并行队列,同步任务,不需要创建线程
            并行队列,异步任务,有多少个任务,就开N个线程执行
      通过GCD,开发者不用再直接跟线程打交道,只需要向队列中添加代码块即可
      GCD在后端管理着一个线程池,GCD不仅决定着代码块将在哪个线程被执行,它还根据可用的系统资源对这些线程进行
管理,从而让开发者从线程管理的工作中解放出来,通过集中的管理线程,缓解大量线程被创建问题
      使用GCD,开发者可以将工作考虑为一个队列,而不是一堆线程,这种并行的抽象模型更容易掌握和使用 
    
 
 
 
 
iOS开发多线程网络———多线程概念及GCD,布布扣,bubuko.com
iOS开发多线程网络———多线程概念及GCD
标签:style   class   blog   code   http   ext   
原文地址:http://www.cnblogs.com/MoGuiBianCheng/p/3784817.html