1. gcd定时器
一个简单的封装
@interface CXGCDTimer : NSObject
+(instancetype)timerWithTimeInterval:(NSTimeInterval)interval repeats:(BOOL)repeats block:(void (^)())block;`
/**
暂停
*/
-(void)suspend;
/**
清除定时器
*/
-(void)clear;
@end
#import "CXGCDTimer.h"
@interface CXGCDTimer ()
@property(nonatomic,copy)dispatch_block_t block;
@property(nonatomic, strong)dispatch_source_t timer;
@end
@implementation CXGCDTimer
+(instancetype)timerWithTimeInterval:(NSTimeInterval)interval repeats:(BOOL)repeats block:(void (^)())block
{
CXGCDTimer *gcdTimer = [[CXGCDTimer alloc]init];
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, interval * NSEC_PER_SEC, 0 * NSEC_PER_SEC);
dispatch_source_set_event_handler(timer, block);
dispatch_resume(timer);
gcdTimer.timer = timer;
return gcdTimer;
}
-(void)suspend
{
dispatch_suspend(self.timer);
}
-(void)clear
{
if (self.timer) {
dispatch_source_cancel(self.timer);
self.timer = nil;
}
self.block = nil;
}
2. gcd队列
- 和operation queue一样都是基于队列的并发API,他们通过集中管理大家协同使用的线程池
- 公开的5个不同队列:运行在主线程的main queue,3个不同优先级的后台队列(high priority queue,default priority queue,low priority queue),以及一个优先级更低的后台队列background priority queue(用于I/O)
- 可创建自定义队列:串行或者并行队列。自定义一般放在default priority queue和main queue
- 操作是在多线程上还是单线程主要是看队列的类型和执行方法,并行队列异步执行才能在多线程,并行队列同步执行只会在这个并行队列在队列中被分配的那个线程执行。
基本概念
- 系统的两个标准队列
//全局队列,一个并行队列
dispatch_queue_t globalQueue = dispatch_get_global_queue(0, 0);
//主队列,主线程中的唯一队列,一个串行队列,所有的UI都是在主线程中完成
dispatch_queue_t mainQueue = dispatch_get_main_queue();
- 自定义队列
//串行队列
dispatch_queue_t serialQueue = dispatch_queue_create("serialQueue", DISPATCH_QUEUE_SERIAL);
//并行队列
dispatch_queue_t concurrentQueue = dispatch_queue_create("concurrentQueue", DISPATCH_QUEUE_CONCURRENT);
- 同步、异步线程创建
dispatch_sync(..., <#^(void)block#>)
dispatch_async(..., <#^(void)block#>)
队列
- Serial:又叫private dispatch queues,同时只能执行一个任务。Serial queue常用来同步访问特定的资源或数据。当你创建多个serial queue时,虽然各自是同步的,但是serial queue之间是并发执行的.
- Main dispatch queue:主队列,全局可用的serial queue,在应用程序主线程上执行任务
- concurrent:又叫global dispatch queue,可以并发执行多个任务,但是执行完成顺序是随机的。系统提供四个全局并发队列,这四个队列有着对应的优先级,用户不能够创建全局队列,只能获取。
dispatch_queue_t globalQueue = dispatch_get_global_queue(0, 0);
- user create queue:用户自己定义的队列,可以用dispatch_queue_create函数,函数有两个参数,第一个是自定义的队列名,第二个是队列类型,默认为NULL或者DISPATCH_QUEUE_SERIAL的是串行,参数为DISPATCH_QUEUE_CONCURRENT是并行队列。
dispatch_group_enter、dispatch_group_leave和dispatch_group_asyn.
NSLog(@"任务开始");
dispatch_group_t group = dispatch_group_create();
dispatch_group_enter(group);
dispatch_async(dispatch_get_global_queue(0, 0), ^{
sleep(5);
NSLog(@"异步并行队列1");
dispatch_group_leave(group);
});
dispatch_group_enter(group);
dispatch_async(dispatch_get_global_queue(0, 0), ^{
sleep(10);
NSLog(@"异步并行队列2");
dispatch_group_leave(group);
});
dispatch_group_notify(group, dispatch_get_global_queue(0, 0), ^{
NSLog(@"任务完成");
});
NSLog(@"任务开始");
dispatch_group_t group = dispatch_group_create();
dispatch_group_async(group, dispatch_get_global_queue(0, 0), ^{
sleep(5);
NSLog(@"async异步并行队列1");
});
dispatch_group_async(group, dispatch_get_global_queue(0, 0), ^{
sleep(8);
NSLog(@"async异步并行队列2");
});
dispatch_group_notify(group, dispatch_get_global_queue(0, 0), ^{
NSLog(@"任务完成");
});
dispatch_group_enter和dispatch_group_leave需要成对出现。当enter和leave之间执行的任务是同步的时候,可以用dispatch_group_async代替,都会在任务执行完成后触发dispatch_group_notify通知。
当enter和leave之间执行的任务是异步的时候,不能代替。
- 信号量
dispatch_semaphore_t semaphore = dispatch_semaphore_create(0);
dispatch_async(dispatch_get_global_queue(0, 0), ^{
sleep(2);
NSLog(@"semaphore");
dispatch_semaphore_signal(semaphore);
});
dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER);
NSLog(@"xxxxxx");
dispatch_semaphore_t可以达到锁的目的
- 死锁
在串行队列里同步调用此串行队列的同步任务就会死锁
NSLog(@"00000");
dispatch_sync(dispatch_get_main_queue(), ^{
dispatch_sync(dispatch_get_main_queue(), ^{
NSLog(@"111111");
});
});
NSLog(@"22222");
当前串行队列里面同步执行当前串行队列就会死锁,解决的方法就是将同步的串行队列放到另外一个线程就能够解决。
细说GCD(Grand Central Dispatch)如何用
使用dispatch_group来进行线程同步