起标题要低调点,不喜欢那种用标题来骗小伙伴进来刷流量,默默的走心就好了。喜欢的小伙伴点个喜欢哦。。。
一、pthread (了解)
#import <pthread.h>
// 创建
pthread_t thread;
pthread_create(&thread, NULL, run, NULL);
void * run(void *param)
{
// 耗时操作
return NULL;
}
二、NSThread(掌握)
// 创建1.
NSThread *thread = [[NSThread alloc] initWithTarget:self selector:@selector(run:) object:@"jack"];
thread.name = @"my-thread";
[thread start];
// 创建2.
[NSThread detachNewThreadSelector:@selector(run:) toTarget:self withObject:@"rose"];
// 创建3.
[self performSelectorInBackground:@selector(run:) withObject:@"jack"];
// 耗时操作
- (void)run:(NSString *)param
{
}
// 其他
[NSThread sleepForTimeInterval:2]; // 让线程睡眠2秒(阻塞2秒)
[NSThread sleepUntilDate:[NSDate dateWithTimeIntervalSinceNow:2]];
[NSThread sleepUntilDate:[NSDate distantFuture]];// 睡到死。。
[NSThread exit]; // 直接退出线程
[NSThread currentThread]; // 当前线程
[NSThread mainThread]; // 主线程
// 加锁 ,互斥锁,缺点需要消耗大量的CPU资源
// 线程同步
@synchronized(self) {
// 需要锁定的代码
}
// 延迟执行
[self performSelector:<#(nonnull SEL)#> withObject:nil afterDelay:<#(NSTimeInterval)#>];
// 线程通讯
// 回到主线程,显示图片
[self.imageView performSelector:@selector(setImage:) onThread:[NSThread mainThread] withObject:image waitUntilDone:NO];
[self.imageView performSelectorOnMainThread:@selector(setImage:) withObject:image waitUntilDone:NO];
[self performSelectorOnMainThread:@selector(showImage:) withObject:image waitUntilDone:YES];// YES 是等完事,向下走 NO就是不等,直接走
- (void)showImage:(UIImage *)image
{
self.imageView.image = image;
}
三、GCD(掌握)
// 创建并发队列
dispatch_queue_t queue = dispatch_queue_create("com.yzgcode.queue", DISPATCH_QUEUE_CONCURRENT);
// 创建串行队列
dispatch_queue_t queue = dispatch_queue_create("com.yzgcode.queue", DISPATCH_QUEUE_SERIAL);// 第二个参数为NULL也可
// 获得全局并发队列
dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
// 获得主队列, 使用的时候注意点,别玩死就OK
dispatch_queue_t queue = dispatch_get_main_queue();
// 其他
// 获取当前队列的名字
dispatch_queue_get_label(DISPATCH_CURRENT_QUEUE_LABEL)
// 不能是全局的,然后会分开(自己领会吧。。)
dispatch_barrier_async(<#dispatch_queue_t queue#>, <#^(void)block#>)
// 延迟
// 在x秒后把任务追加到队列中,并不是在x秒后执行
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(<#delayInSeconds#> * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
});
// 快速遍历
dispatch_apply 将外面的线程(main线程)阻塞了, 他会等待其他所有的循环运行完毕才会往下执行
dispatch_apply(3, queue, ^(size_t index) {
NSLog(@"apply loop: %zu, %@", index, [NSThread currentThread]);
});
// 队列组
dispatch_group_t group = dispatch_group_create();
dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
dispatch_group_async(group, queue, ^{
});
dispatch_group_async(group, queue, ^{
});
dispatch_group_notify(group, dispatch_get_main_queue(), ^{
});
// 优先级
dispatch_queue_t mySerialDispatchQueue = dispatch_queue_create("com.yzgcode.queue", NULL);
dispatch_queue_t globalDispatchQueueBackground = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_BACKGROUND, 0);
dispatch_set_target_queue(mySerialDispatchQueue, globalDispatchQueueBackground);
上面的代码,dispatch_set_target方法的第一个参数是要设置优先级的队列,第二队参数是则是参考的的队列,使第一个参数与第二个参数具有相同的优先级。
dispatch_suspend 挂起指定的队列
dispatch_supend(queue);
dispatch_resume 恢复指定队列
dispatch_resume(queue);
线程挂起对已执行的任务没有影响,挂起后,还未执行的任务停止执行,待恢复后,这些任务继续执行
Dispatch Semaphore(信号量)
信号量持有计数信号,如果信号量计数大于或等于1,那么允许线程执行,否则线程将阻塞
// 创建信号量
dispatch_semaphore_t semaphore = dispatch_semaphore_create(1); // 1 表示信号量计数初始值
发出等待信号(信号量计数减1)
dispatch_semaphore_wait(_semaphore, DISPATCH_TIME_FOREVER);
发出通行信号 (信号量计数加1)
dispatch_semaphore_signal(_semaphore);
例:
- (IBAction)createSemaphore:(id)sender {
dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
_semaphore = dispatch_semaphore_create(0); //创建一个计数为零的信号量
for (int a = 0 ; a<10 ;a ++) { //向队列添加个任务 dispatch_async(queue, ^{
dispatch_semaphore_wait(_semaphore, DISPATCH_TIME_FOREVER); //进来信号量减1,当它为零的时候不会再减变为负数
NSLog(@"%i",a);
});
}
}
- (IBAction)semaphorePlusOne:(id)sender {
//信号量加1
dispatch_semaphore_signal(_semaphore);
}
1、第一个函数创建了计数量为零的信号量。当所有的任务,跑到dispatch_semaphore_wait这个方法的时候,因为信号量当前计数为0,那么它们只能阻塞在这里了。
2、执行第二个方法,给信号量加1,那么在上面阻塞的任务抽出一个执行。
四、NSOperation
4.1基本使用
NSBlockOperation *op = [NSBlockOperation blockOperationWithBlock:^{
// 在主线程
NSLog(@"下载1------%@", [NSThread currentThread]);
}];
// 添加额外的任务(在子线程执行)
[op addExecutionBlock:^{
NSLog(@"下载2------%@", [NSThread currentThread]);
}];
[op addExecutionBlock:^{
NSLog(@"下载3------%@", [NSThread currentThread]);
}];
[op addExecutionBlock:^{
NSLog(@"下载4------%@", [NSThread currentThread]);
}];
[op start];
// 创建队列
NSOperationQueue *queue = [[NSOperationQueue alloc] init];
// 创建操作(任务)
// 创建NSInvocationOperation
NSInvocationOperation *op1 = [[NSInvocationOperation alloc] initWithTarget:self selector:@selector(download1) object:nil];
NSInvocationOperation *op2 = [[NSInvocationOperation alloc] initWithTarget:self selector:@selector(download2) object:nil];
// 创建NSBlockOperation
NSBlockOperation *op3 = [NSBlockOperation blockOperationWithBlock:^{
NSLog(@"download3 --- %@", [NSThread currentThread]);
}];
[op3 addExecutionBlock:^{
NSLog(@"download4 --- %@", [NSThread currentThread]);
}];
[op3 addExecutionBlock:^{
NSLog(@"download5 --- %@", [NSThread currentThread]);
}];
NSBlockOperation *op4 = [NSBlockOperation blockOperationWithBlock:^{
NSLog(@"download6 --- %@", [NSThread currentThread]);
}];
// 创建YZGOperation // 自定义Operation,重写main方法
// 在耗时操作的时候加判断 if(self.isCancelled) return;
YZGOperation *op5 = [[YZGOperation alloc] init];
// 添加任务到队列中
[queue addOperation:op1]; // [op1 start]
[queue addOperation:op2]; // [op2 start]
[queue addOperation:op3]; // [op3 start]
[queue addOperation:op4]; // [op4 start]
[queue addOperation:op5]; // [op5 start]
- (void)download1
{
NSLog(@"download1 --- %@", [NSThread currentThread]);
}
- (void)download2
{
NSLog(@"download2 --- %@", [NSThread currentThread]);
}
4.2简单方法
NSOperationQueue *queue = [[NSOperationQueue alloc] init];
[queue addOperationWithBlock:^{
NSLog(@"download1 --- %@", [NSThread currentThread]);
}];
4.3 一些属性
// 创建队列
NSOperationQueue *queue = [[NSOperationQueue alloc] init];
// 设置最大并发操作数
queue.maxConcurrentOperationCount = 1; // 就变成了串行队列
queue.suspended = YES;// 暂停执行
[queue cancelAllOperations]; // 取消
4.4依赖
类似于GCD 队列组
NSOperationQueue *queue = [[NSOperationQueue alloc] init];
NSBlockOperation *op1 = [NSBlockOperation blockOperationWithBlock:^{
NSLog(@"download1----%@", [NSThread currentThread]);
}];
NSBlockOperation *op2 = [NSBlockOperation blockOperationWithBlock:^{
NSLog(@"download2----%@", [NSThread currentThread]);
}];
NSBlockOperation *op3 = [NSBlockOperation blockOperationWithBlock:^{
NSLog(@"download3----%@", [NSThread currentThread]);
}];
NSBlockOperation *op4 = [NSBlockOperation blockOperationWithBlock:^{
for (NSInteger i = 0; i<10; i++) {
NSLog(@"download4----%@", [NSThread currentThread]);
}
}];
NSBlockOperation *op5 = [NSBlockOperation blockOperationWithBlock:^{
NSLog(@"download5----%@", [NSThread currentThread]);
}];
op5.completionBlock = ^{
NSLog(@"op5执行完毕---%@", [NSThread currentThread]);
};
// 设置依赖
[op3 addDependency:op1];
[op3 addDependency:op2];
[op3 addDependency:op4];
[queue addOperation:op1];
[queue addOperation:op2];
[queue addOperation:op3];
[queue addOperation:op4];
[queue addOperation:op5];
4.5 线程间通讯
[[[NSOperationQueue alloc] init] addOperationWithBlock:^{
// 图片的网络路径
NSURL *url = [NSURL URLWithString:@"http://img.pconline.com.cn/images/photoblog/9/9/8/1/9981681/200910/11/1255259355826.jpg"];
// 加载图片
NSData *data = [NSData dataWithContentsOfURL:url];
// 生成图片
UIImage *image = [UIImage imageWithData:data];
// 回到主线程
[[NSOperationQueue mainQueue] addOperationWithBlock:^{
self.imageView.image = image;
}];
}];