06-GCD基本使用和组合

GCD


GCD的概念(自动管理)

  • GCD有两个核心概念
    • 任务 :执行什么操作
    • 队列 :用来存放任务
  • GCD的使用步骤
    • 定制任务
      • 确定想做的事
    • 将任务添加到队列中
      • GCD会自动将队列中的任务取出,放到对应的线程中执行
      • FIFO 先进先出原则
  • 执行任务
    • 同步
      • dispath_sync(dispath_queue_t queue,^(void)block)
    • 异步
      • dispath_async(dispath_queue_t queue,^(void)block)
    • 同步和异步的区别:
      • 同步: 只能在当前线程中执行任务,不具备开启新县城的能力
      • 异步: 可以在新的线程中执行任务,具备开启新线程的能力
//dispath_queue_t 队列
//^(void)block 任务
dispath_async(dispath_queue_t queue,^(void)block)

同步/异步/并发/串行

  • 同步:不能开启新线程

  • 异步:可以开启新线程

  • 并发:可以开启多个子线程

  • 串行:只能在一个线程中执行(默认是串行队列)

  • 注意

    • 如果是同步函数,那么会等到函数中的任务执行完毕,才会执行后面的代码
    • 如果是异步函数,那么不用等到函数中的任务执行完毕,就会执行后面的代码

--

系统提供的并发队列

// 系统内部已经给我们提供好了一个现成的并发队列
dispath_queue_t queue = dispath_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT,0);
//异步函数调用
dispath_async(queue,^(void)block)
系统提供的并发队列参数解析:
  • 第一个参数: iOS8以前是优先级, iOS8以后是服务质量

    • iOS8以前

        • DISPATCH_QUEUE_PRIORITY_HIGH 高优先级 2
        • DISPATCH_QUEUE_PRIORITY_DEFAULT: 默认的优先级 0
        • DISPATCH_QUEUE_PRIORITY_LOW: 低优先级 -2
        • DISPATCH_QUEUE_PRIORITY_BACKGROUND:
    • iOS8以后

        • QOS_CLASS_USER_INTERACTIVE 0x21 用户交互(用户迫切想执行任务)
        • QOS_CLASS_USER_INITIATED 0x19 用户需要
        • QOS_CLASS_DEFAULT 0x15 默认
        • QOS_CLASS_UTILITY 0x11 工具(低优先级, 苹果推荐将耗时操作放到这种类型的队列中)
        • QOS_CLASS_BACKGROUND 0x09 后台
        • QOS_CLASS_UNSPECIFIED 0x00 没有设置
  • 第二个参数: 废物(写0就是default,不管在ios8以前还是以后)

    • dispatch_queue_t queue = dispatch_get_global_queue(0, 0);

创建自定义队列,将任务加到队列中

  • 任务多的话使用dispath_async会开启新线程
  • 如果是并发,那么会开启多个线程(根据任务多少决定开启线程个数,一个线程可能处理多个任务)
串行队列+异步函数调用
  • 会开启新的线程,但只会开启一个新的线程
- (void)syncSerial{
 // 1.创建串行队列
    dispatch_queue_t queue = dispatch_queue_create("com.520it.ln", DISPATCH_QUEUE_SERIAL);
    //#define DISPATCH_QUEUE_SERIAL NULL
    //串行等于NULL
    /*
     能够创建新线程的原因:
     我们是使用"异步"函数调用
     只创建1个子线程的原因:
     我们的队列是串行队列
     */
    // 2.将任务添加到队列中
    dispatch_async(queue, ^{
        NSLog(@"任务1  == %@", [NSThread currentThread]);
    });
    dispatch_async(queue, ^{
        NSLog(@"任务2  == %@", [NSThread currentThread]);
    });
    dispatch_async(queue, ^{
        NSLog(@"任务3  == %@", [NSThread currentThread]);
    });
}
串行队列+同步函数调用
  • 不会开启新的线程
- (void)syncSeral
{
 // 1.创建串行队列
    dispatch_queue_t queue = dispatch_queue_create("com.520it.ln", DISPATCH_QUEUE_SERIAL);
    /*
     能够创建新线程的原因:
     我们是使用"异步"函数调用
     只创建1个子线程的原因:
     我们的队列是串行队列
     */
    // 2.将任务添加到队列中
    dispatch_sync(queue, ^{
        NSLog(@"任务1  == %@", [NSThread currentThread]);
    });
    dispatch_async(queue, ^{
        NSLog(@"任务2  == %@", [NSThread currentThread]);
    });
    dispatch_async(queue, ^{
        NSLog(@"任务3  == %@", [NSThread currentThread]);
    });
}
并发队列+同步函数调用
- (void)syncConCurrent
{
 // 1.创建串行队列
    dispatch_queue_t queue = dispatch_queue_create("com.520it.ln", DISPATCH_QUEUE_CONCURRENT);
    /*
     能够创建新线程的原因:
     我们是使用"异步"函数调用
     只创建1个子线程的原因:
     我们的队列是串行队列
     */
    // 2.将任务添加到队列中
    dispatch_sync(queue, ^{
        NSLog(@"任务1  == %@", [NSThread currentThread]);
    });
    dispatch_async(queue, ^{
        NSLog(@"任务2  == %@", [NSThread currentThread]);
    });
    dispatch_async(queue, ^{
        NSLog(@"任务3  == %@", [NSThread currentThread]);
    });
}
并发队列+异步函数调用
- (void)asyncConCurrent
{
 // 1.创建串行队列
    dispatch_queue_t queue = dispatch_queue_create("com.520it.ln", DISPATCH_QUEUE_CONCURRENT);
    /*
     能够创建新线程的原因:
     我们是使用"异步"函数调用
     只创建1个子线程的原因:
     我们的队列是串行队列
     */
    // 2.将任务添加到队列中
    dispatch_async(queue, ^{
        NSLog(@"任务1  == %@", [NSThread currentThread]);
    });
    dispatch_async(queue, ^{
        NSLog(@"任务2  == %@", [NSThread currentThread]);
    });
    dispatch_async(queue, ^{
        NSLog(@"任务3  == %@", [NSThread currentThread]);
    });
}

--

主队列

  • 特点: 只要将任务添加到主队列中,那么任务一定会在主线程中执行,无论你是调用同步函数还是异步函数
  • 主队列默认是串行
  • 异步 + 主队列 :不会创建新的线程,并且任务是在主线程中执行
  • 如果是异步函数,那么不用等到函数中的任务执行完毕,就会执行后面的代码,不会产生死锁.
- (void)asyncMain{
dispath_queue_t queue = dispatch_get_main_queue();

//即便是异步函数,在主队列中也不会创建新的线程
dispath_async(queue,^{
	NSLog(@"%@",[NSThread currentThread]);
});
}
注意避免死锁
  • 导致死锁的原因(同步+主队列)
    • sync函数在主线程中执行,并且会等待block执行完毕,先调用
    • block是添加到主队列中的,也需要主线程中执行,后调用
    • 注意:如果是同步函数,那么会等到函数中的任务执行完毕,才会执行后面的代码
- (void) viewDidLoad
{
//主队列默认是串行的
	dispath_queue_t queue = dispatch_get_main_queue();

	dispath_sync(queue,^{
	NSLog(@"%@",[NSThread currentThread]);
	});
}
  • 解决办法
    • block在子线程执行
- (void) viewDidLoad
{
//系统提供的并发队列
	dispath_queue_t = queue = dispatch_get_global_queue(0,0);
	
	dispath_async(queue,^{
		//获取主线程
		dispath_queue_t queue = dispatch_get_main_queue();
		
		//小技巧:
		//此时使用同步sync:NSLog(@"--------");一定会在dispatch执行完毕后执行
		//若使用异步async:NSLog(@"--------");不一定会在dispatch执行完毕后执行
		dispath_sync(queue,^{
		NSLog(@"%@",[NSThread currentThread]);
		});
		NSLog(@"--------");
	});
}
posted @ 2015-09-03 16:19  紫之灵玲  阅读(140)  评论(0编辑  收藏  举报