******************************************************************************************
pthread
******************************************************************************************
pthread 使用方法
pthread是C语言的多线程库,使用pthread需要首先添加头文件
1. 声明和实现一个函数
void *task(void *param){
// 执行任务的代码
return NULL;
}
2. 在合适的位置开启多线程执行之前声明的函数
// 声明一个线程
pthread_t thread;
// 调用线程函数
pthread_create(&thread, NULL, task, NULL);
3. 判断两个线程是否相同的函数
pthread_equal(threadA, threadB);
******************************************************************************************
NSThread
******************************************************************************************
NSThread 使用方法
NSThread 是OC的方法,封装了pthread,使操作更加面向对象。
NSThread的方法
// 创建线程的方法
NSThread *thread = [[NSThread alloc] initWithTarget:self selector:@(task) object:nil];
// 设置线程名称
thread.name = @"线程方法";
// 设置线程优先级
thread.threadPriority = 0.0-1.0; // 默认0.5
// 启动线程
[thread start];
**************************************************************
// 使用分离的方法获得线程
[NSThread detachNewThreadSelector:@selector(task) toTarget:self withObject:nil];
**************************************************************
// 开启一条后台的线程
[self performSelectInBackground:@selector(task) withObject:nil];
**************************************************************
// 获得主线程
NSThread *mainThread = [NSThread mainThread];
**************************************************************
// 获得当前线程
NSThread *currentThread = [NSThread currentThread];
**************************************************************
线程的操作方法
// start方法 new -> runabled
[thread start];
// 线程进入阻塞状态 run -> blocked
[NSThread sleepUntilDate:date];
[NSThread sleepForTimeInterval:timeInterval];
// 强制停止线程
[NSThread exit];
使用线程锁
@synchronized(self){
// 为了防止死锁,使用线程锁可以让线程访问一块资源的时候为它加上锁。
// 一般使用self,必须是全局唯一的对象。
// 加锁的代码
}
线程之间的通信
// 线程通信是直接调用主线程的方法
[self performSelectorOnMainThread:@selector(task) withObject:nil waitUntilDone:YES/NO];
// 最后一个参数指是否等待task完成再执行后面的代码。
// 判断当前线程是否为主线程
BOOL isMainThread = [[NSThread currentThread] isMainThread];
******************************************************************************************
GCD
******************************************************************************************
GCD: Grand Central Dispatch
GCD 能够充分利用CPU多核进行并行运算
创建队列
1. 创建并发队列 Concurrent Dispatch Queue
dispatch_queue_t queue = dispatch_queue_create("com.baidu.download", DISPATCH_QUEUE_CONCURRENT);
2. 获得全局并发队列
dispatch_queue_t queue = dispatch_get_global_queue(0,0);
{ // 第一个参数是优先级
DISPATCH_QUEUE_PRIORITY_HIGH
DISPATCH_QUEUE_PRIORITY_DEFAULT
DISPATCH_QUEUE_PRIORITY_LOW
DISPATCH_QUEUE_PRIORITY_BACKGROUND
}
3. 创建串行队列 Serial Dispatch Queue
dispatch_queue_t queue = dispatch_queue_create("com.baidu.download", DISPATCH_QUEUE_SERIAL)
4. 获得主队列 UI线程 (全局串行队列)
dispatch_queue_t queue = dispatch_get_main_queue();
创建函数
1. 同步函数 // queue不能使用主队列,不然会产生死锁。
dispatch_sync(queue, block);
2. 异步函数
dispatch_async(queue, block);
GCD常用函数
1. 延迟执行代码的方法 // 第一个参数指从现在开始, 第二个参数指两秒后开始
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(2.0 * NSEC_PER_SEC)), queue, ^{...});
2. 一次性代码: 单例demo
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{...});
3. 栅栏函数 // queue不能使用全局并发队列
dispatch_barrier_async(queue, ^{...});
4. 快速迭代代码 // 第一个参数是迭代次数 ,
// 第二个参数使用并发队列,如果使用串行队列就没有意义了.
dispatch_apply(n, queue, ^(size_t i){...});
队列组函数
// 创建队列组
dispatch_group_t group = dispatch_group_create();
// 执行队列组函数
dispatch_group_async(group, queue, ^{...});
// 监听队列组函数是否执行完毕,组内线程执行完毕后执行自己的函数
// 这个函数是异步执行的,不会阻塞后续代码执行
dispatch_group_notify(group, queue, ^{...});
// wait函数会阻塞线程,直到队列组任务结束
dispatch_group_Wait(group, DISPATCH_TIME_FOREVER);
******************************************************************************************
NSOperation
******************************************************************************************
NSOperation
NSOperation 是个抽象类,与NSOperationQueue搭配使用时可以开启多线程。它有两个子类,NSInvocationOperation 和 NSBlockOperation。
使用方法: 封装操作 --> 添加到队列。
封装操作的方法
// 使用NSInvocationOperation封装操作并启动。这时候不会开线程
NSInvocationOperation *operation = [[NSInvocationOperation alloc] initWithTarget:self selector:@selector(task) object:nil];
[operation start];
****************************************************************
// 使用NSBlockOperation封装操作。封装的操作不会开启线程
NSBlockOperation *operation = [NSBlockOperation blockOperationWithBlock:^{...}];
// NSBlockOperation有一个追加操作的方法,追加的操作会自动开启线程执行。
[operation addExecutionBlock:^{...}];
[operation start];
****************************************************************
// 自定义[操作]
// 自定义一个继承自NSOperation的类,重写main方法,将操作放到main方法中,使用init方法创建出来后可以直接添加到队列中执行操作。
//*****main方法中存放需要封装的耗时操作*****
添加到队列
// NSOperation里有两种队列,主队列和非主队列。
// 主队列获得方法
NSOperationQueue *mainQueue = [NSOperationQueue mainQueue];
****************************************************************
// 非主队列只能创建,init出来的队列默认为非主队列。
NSOperationQueue *queue = [[NSOperationQueue alloc]
init];
// 操作非主队列的maxConcurrentOperationCount属性可以实现并发和串行的模式
// ****当i=1的时候,队列也会开多条线程,但是多个操作在不同线程中会串行执行****
// 当i=0时表示最大并发数为0,不会开启线程则不会执行操作
// i=-1,默认值,表示最大值。
queue.maxConcurrentOperationCount = (NSInteger)i;
// 将任务添加到队列,队列会自动调用任务的start方法并且开启线程
[queue addOperation:operation];
****************************************************************
// 队列可以使用快捷添加操作的方法
[queue addOperationWithBlock:^{}];
控制队列内操作的方法
// 操作的暂停和继续
// ***已经开始的线程是无法暂停的***
queue.suspended = YES; // 暂停操作
queue.suspended = NO; // 开始操作
****************************************************************
// 取消操作
// ***已经开始的操作是无法取消的,取消后无法再次启动***
// 因为耗时操作执行时间太长,导致取消操作后已经启动的线程还在继续执行,可以使用在多个
// 位置添加代码判断是否取消了操作,提升用户体验.
// cancelAllOperations方法是调用所有操作的cancel方法,所以使用以下代码
// *** if(self.isCancelled) return; ***[添加到耗时操作内部随时判断]
[queue cancelAllOperations];
****************************************************************
// 控制操作的执行顺序
// 使用依赖的方法控制每个操作的执行顺序,注意不能产生循环以来。
// ***即使操作在不同的队列,也可以跨队列添加依赖关系***
[operationA addDependency:operationB];
// 执行完B之后才会执行A
// 使用监听的方法控制操作的执行顺序
// A执行完毕后才会进入block执行,block的代码系统会自动开启多线程执行。
operationA.completionBlock = ^{...};【异步执行】
线程之间的通信
// NSOperation的线程间通信可以直接使用队列调用方法
// 在非主队列中调用主队列操作可以直接在非主队列操作中调用方法:
[[NSOperationQueue mainQueue] addOperationWithBlock:^{...}];