iOS学习6_多线程NSThread和GCD NSThread GCD:Grand-Central-Dispatch GCD的其他使用: 线程之间的通信:在主线程修改UI

iOS学习6_多线程NSThread和GCD
NSThread
GCD:Grand-Central-Dispatch
GCD的其他使用:
线程之间的通信:在主线程修改UI

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);
iOS学习6_多线程NSThread和GCD
NSThread
GCD:Grand-Central-Dispatch
GCD的其他使用:
线程之间的通信:在主线程修改UI

最常使用:

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) {
}];