iOS中常用的多线程操作有(
NSThread,
NSOperation
GCD
)
1.NSThread
线程的创建
1.
NSThread *thread = [[NSThread alloc] initWithTarget:self selector:@selector(runAction:) object:nil]; thread.name = @"thread--1"; [thread start];
2.创建线程后自动启动线程
[NSThread detachNewThreadSelector:@selector(runAction:) toTarget:self withObject:nil];
PS:子线程中默认RunLoop是不启动的(主线程中的runloop是程序启动就运行)所以如果需要保持线程持续运行需要手动启动runloop
为了保证线程不死,我们考虑在子线程中加入RunLoop 但是由于RunLoop中没有没有源,就会自动退出RunLoop,所以我们要为子线程添加一个RunLoop,
并且为这个RunLoop添加源(保证RunLoop不退出) 在 runAction方法中加入如下代码:
//添加源 [[NSRunLoop currentRunLoop] addPort:[NSPort port] forMode:NSDefaultRunLoopMode]; // //启动RunLoop [[NSRunLoop currentRunLoop] run];
2.NSOperation
使用子类
1.NSInvocationOperation:
同步
// 1.创建NSInvocationOperation对象 NSInvocationOperation *op = [[NSInvocationOperation alloc] initWithTarget:self selector:@selector(runAction) object:nil]; // 2.调用start方法开始执行操作 //在没有使用NSOperationQueue、单独使用NSInvocationOperation的情况下, //NSInvocationOperation在主线程执行操作,并没有开启新线程。 [op start];
异步
// 1. 创建队列 NSOperationQueue *queue = [[NSOperationQueue alloc] init]; // 2.创建NSInvocationOperation对象 NSInvocationOperation *op = [[NSInvocationOperation alloc] initWithTarget:self selector:@selector(runAsnysAction) object:nil]; [queue addOperation:op];
2.NSBlockOperation'
NSOperationQueue *queue = [[NSOperationQueue alloc] init]; NSBlockOperation *op0 = [NSBlockOperation blockOperationWithBlock:^{ NSLog(@"addDependency0当前线程%@", [NSThread currentThread]); }]; NSBlockOperation *op1 = [NSBlockOperation blockOperationWithBlock:^{ NSLog(@"addDependency1当前线程%@", [NSThread currentThread]); }]; NSBlockOperation *op2 = [NSBlockOperation blockOperationWithBlock:^{ NSLog(@"addDependency2当前线程%@", [NSThread currentThread]); }]; [op0 addDependency:op1]; // 添加依赖 这里等op1 op2执行完后再执行op0 [op0 addDependency:op2]; [queue addOperation:op1]; [queue addOperation:op2]; [queue addOperation:op0];
3.CGD
同步执行(sync):只能在当前线程中执行任务,不具备开启新线程的能力
异步执行(async):可以在新的线程中执行任务,具备开启新线程的能力
并发队列(Concurrent Dispatch Queue):可以让多个任务并发(同时)执行(自动开启多个线程同时执行任务),并发功能只有在异步(dispatch_async)函数下才有效
串行队列(Serial Dispatch Queue):让任务一个接着一个地执行(一个任务执行完毕后,再执行下一个任务)
在GCD中一个操作是多线程执行还是单线程执行取决于当前队列类型和执行方法,只有队列类型为并行队列并且使用异步方法执行时才能在多个线程中执行。
串行队列可以按顺序执行,并行队列的异步方法无法确定执行顺序。
UI界面的更新最好采用同步方法,其他操作采用异步方法。
GCD中多线程操作方法不需要使用@autoreleasepool,GCD会管理内存
如果在主线程中运用主队列同步,也就是把任务放到了主线程的队列中。
而同步对于任务是立刻执行的,那么当把第一个任务放进主队列时,它就会立马执行。
可是主线程现在正在处理 syncMain 方法,任务需要等 syncMain 执行完才能执行。
syncMain 执行到第一个任务的时候,又要等第一个任务执行完才能往下执行第二个和第三个任务。
这样 syncMain 方法和第一个任务就开始了互相等待,形成了死锁。
dispatch_queue_t mainQueue = dispatch_get_main_queue(); dispatch_sync(mainQueue, ^{ //do something });
队列创建方法:
串行队列:
dispatch_queue_t queue= dispatch_queue_create("test.queue", DISPATCH_QUEUE_SERIAL);
并行队列:
Dispatch_queue_t queue= dispatch_queue_create("test.queue", DISPATCH_QUEUE_CONCURRENT)
dispatch_get_global_queue//全局并发队列
GCD定时器
// 获得队列 // dispatch_queue_t queue = dispatch_get_global_queue(0, 0); dispatch_queue_t queue = dispatch_get_main_queue(); // 创建一个定时器(dispatch_source_t本质还是个OC对象) self.timer = dispatch_source_create(DISPATCH_SOURCE_TYPE_TIMER, 0, 0, queue); // 何时开始执行第一个任务 // dispatch_time(DISPATCH_TIME_NOW, 3.0 * NSEC_PER_SEC) 比当前时间晚3秒 dispatch_time_t start = dispatch_time(DISPATCH_TIME_NOW, (int64_t)(3.0 * NSEC_PER_SEC)); uint64_t interval = (uint64_t)(1.0 * NSEC_PER_SEC); dispatch_source_set_timer(self.timer, start, interval, 0); // 设置回调 dispatch_source_set_event_handler(self.timer, ^{ NSLog(@"------------%@", [NSThread currentThread]); count++; if (count == 10) { // 取消定时器 dispatch_cancel(self.timer); self.timer = nil; count = 0; } }); // 启动定时器 dispatch_resume(self.timer);
dispatch_group_t:
// 创建一个队列组 dispatch_group_t group = dispatch_group_create(); dispatch_group_async(group, queue, ^{ //do something 1 }); dispatch_group_async(group, queue, ^{ //do something 2 }); dispatch_group_notify(group, queue, ^{ //当1和2都执行完后,合并执行 });
dispatch_barrier_async:
dispatch_barrier_async函数的作用与barrier的意思相同,在进程管理中起到一个栅栏的作用,它等待所有位于barrier函数之前的操作执行完毕后执行,并且在barrier函数执行之后,barrier函数之后的操作才会得到执行,该函数需要同dispatch_queue_create函数生成的concurrent Dispatch Queue队列一起使用
dispatch_queue_t queue = dispatch_queue_create("my-queue", DISPATCH_QUEUE_CONCURRENT); dispatch_async(queue, ^{ //1 }); dispatch_sync(queue, ^{ //2 }); dispatch_barrier_async(queue, ^(){ //当1,2执行完后才会执行此block }); //等dispatch_barrier_async执行完再执行 dispatch_async(queue, ^{ 、 }); dispatch_sync(queue, ^{ });