iOS学习6_多线程NSThread和GCD
NSThread
1.显式创建线程调用start开启
NSThread * thread = [[NSThread alloc]initWithTarget:self selector:@selector(run:) object:_url]; [thread start];2.隐式创建
[NSThread detachNewThreadSelector:@selector(run:) toTarget:self withObject:_url];3.
[self performSelectorInBackground:@selector(run:) withObject:_url];
使用NSThread类似于Java里面的Thread类,线程同步等也是使用synchronized关键字。
GCD:Grand-Central-Dispatch
苹果提供的多核并行解决方案
自动管理线程生命周期
屏蔽掉了创建线程和管理线程的底层内容,让程序员使用并发编程更容易。
两个概念:任务和队列。
任务:要执行的操作
队列:用来存放任务。
定制自己的任务,然后将任务加入到队列后,GCD会自动从队列取出任务放到对应的线程执行。
相关概念:
同步:和当前线程是一条线,不开启线程dispatch_async函数
异步:开启线程dispatch_sync函数
串行队列:让任务一个接着一个执行
并行队列:多个任务同时执行,自动开启线程,只有在异步的情况下才有效。一般使用全局并发队列
队列决定任务怎么执行不决定是否开启线程;同步/异步决定是否开启线程。
创建串行队列:
dispatch_queue_attr_t attr; dispatch_queue_t queue = dispatch_queue_create("qhyuan",attr);
获取全局并发队列:
diapstch_queue_tqueue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
最常使用:
1. 异步函数 + 并行队列
diapstch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0); dispatch_async(queue, ^{// exec task}); dispatch_async(queue, ^{// exec task}); dispatch_async(queue, ^{// exec task});
一般会开启三个线程,并且同时执行。
2.异步函数 + 串行队列
dispatch_queue_attr_t attr; dispatch_queue_t queue = dispatch_queue_create("qhyuan", attr); dispatch_async(queue, ^{// exec task}); dispatch_async(queue, ^{// exec task}); dispatch_async(queue, ^{// exec task});
开启一个线程,并且串行的执行。可以打印出线程id发现是一样的。
3.一个特殊的串行队列:主队列它是一个与主线程相关的队列,自带的一个串行队列。放在主队列中的任务,不论他是同步还是异步都会在主线程中执行,注意,主队列和同步函数使用时,由于是串行的会等到当前任务执行完才会继续往下执行,所以当他后面还有代码为执行就会出问题。因此一般使用异步函数和主队列搭配使用。
特殊之处就在于只有使用的是主队列,那么任务一定在主线程里面执行。
dispatch_async(dispatch_get_main_queue(), ^{ // change UI });
GCD的其他使用:
1.队列组:
使用函数dispatch_group_async(dispatch_group_t group, dispatch_queue_t queue, ^(void){ })
dispatch_group_t 参数就是一个队列组,可以如下创建一个队列组,dispatch_queue_t指定了block里面的任务在那里执行。
dispatch_group_t group = dispatch_group_create();使用队列组的好处是,他会等到扔进队列组的所有任务执行完成后执行下面方法:
dispatch_group_notify(dispatch_group_t group, dispatch_queue_t queue, ^(void)block);2.延迟执行
[NSThread sleepForTimeInterval:];//会卡主线程 dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(delayInSeconds * NSEC_PER_SEC)), queue, ^{ // delayInSeconds秒后执行的内容 });3.一次性代码:
static dispatch_once_t onceToken; dispatch_once(&onceToken, ^{ // 这里的代码只会执行一次 });
线程之间的通信:在主线程修改UI
[self performSelectorOnMainThread:(SEL) withObject:(id) waitUntilDone:(BOOL)]使用GCD方案:
dispatch_async(dispatch_get_main_queue(), ^{ //这里的代码是在主线程执行的 });发送http请求时使用主队列,当然这里的主队列和GCD里面获取主队列不一样。
[NSURLConnection sendAsynchronousRequest:request queue:[NSOperationQueue mainQueue] completionHandler:^(NSURLResponse *response, NSData *data, NSError *connectionError) { }];