1. C语言中的 void * 等同于 OC 中的 id
- (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event {
//创建子线程
pthread_t pthread;
/** 1. 返回值: 返回0表示成功, 非0表示失败 2. 参数: 第一个参数 线程编号的地址 第二个参数 线程的属性 第三个参数 线程要执行的函数void * (*) (void *) void * 指向任何类型的指针 有点类似OC中的id 第四个参数 要执行的函数的参数 */
int result = pthread_create(&pthread, NULL, demo, NULL);
NSLog(@"touchesBegan %@",[NSThread currentThread]);
if (result == 0) {
NSLog(@"成功");
}else {
NSLog(@"失败");
}
}
void *demo(void *param) {
NSLog(@"hello %@",[NSThread currentThread]);
return NULL;
}
1. // alloc init 实例化方法
- (instancetype)initWithTarget:(id)target selector:(SEL)selector object:(nullable id)argumen;
1> 作用: 实例化一个线程对象, 执行 selector 方法
* "注意: 要启动线程, 需要调用 start 方法"
2> 参数
* 提供 selector 方法的对象, 通常是 self (selector方法的拥有者)
* selector 方法
* 传递给 selector 方法的参数
3> start 方法
* 将线程对象放入可调度线程池等待CPU调度
cancel 方法
* 通知线程取消
------------------------------------
2. // 类方法
+ (void)detachNewThreadSelector:(SEL)selector toTarget:(id)target withObject:(nullable id)argument;
1> 作用: 创建并自动启动线程, 执行 selector 方法
2> 参数:
* 提供 selector 方法的对象, 通常是 self (selector方法的拥有者)
* selector 方法
* 传递给 selector 方法的参数
------------------------------------
3. // NSObject 分类方法
- (void)performSelectorInBackground:(SEL)aSelector withObject:(nullable id)arg
1> 作用: 隐式(没有任何跟线程相关的字眼)创建并启动线程,执行 selector 方法
2> 参数:
* selector 方法
* 传递给 selector 方法的参数
3> 注意: "既然是 NSObject 的分类方法, 任何继承自 NSObject 的对象都可以直接调用这个方法,因此 perform 方法使用最灵活"
总结:
** 使用 detach 和 perform 两种方法创建线程更加简便
** 缺点:无法对线程进行更详细的设置
//串行队列 同步执行
-(void) demo1 {
//创建一个串行队列
dispatch_queue_t queue = dispatch_queue_create("qh", DISPATCH_QUEUE_SERIAL);
dispatch_sync(queue, ^{
for (int i = 0 ; i < 10 ; i ++ ) {
NSLog(@"第%d次加载 线程%@",i,[NSThread currentThread]);
}
});
}
//串行队列 异步执行
-(void) demo2{
//创建一个串行队列
dispatch_queue_t queue = dispatch_queue_create("qh", DISPATCH_QUEUE_SERIAL);
for (int i = 0 ; i < 10 ; i ++ ) {
dispatch_async(queue, ^{
NSLog(@"第%d次加载 线程%@",i,[NSThread currentThread]);
});
}
}
//并行队列 同步执行
-(void) demo3{
for (int i = 0 ; i < 10 ; i ++ ) {
dispatch_queue_t queue = dispatch_queue_create("hm", DISPATCH_QUEUE_CONCURRENT);
dispatch_sync(queue, ^{
NSLog(@"第%d次加载 线程%@",i,[NSThread currentThread]);
});
}
}
//并行队列 异步执行
-(void) demo4{
dispatch_queue_t queue = dispatch_queue_create("hm", DISPATCH_QUEUE_CONCURRENT);
for (int i = 0 ; i < 10 ; i ++ ) {
dispatch_async(queue, ^{
NSLog(@"第%d次加载 线程%@",i,[NSThread currentThread]);
});
}
}
//主线程 同步队列 死锁
-(void) demo5{
for (int i = 0 ; i < 10 ; i ++ ) {
dispatch_sync(dispatch_get_main_queue(), ^{
NSLog(@"第%d次加载 线程%@",i,[NSThread currentThread]);
});
}
}
//主线程 异步队列
-(void) demo6{
for (int i = 0 ; i < 10 ; i ++ ) {
dispatch_async(dispatch_get_main_queue(), ^{
NSLog(@"第%d次加载 线程%@",i,[NSThread currentThread]);
});
}
}
建NSInvocationOperation对象
- (id)initWithTarget:(id)target selector:(SEL)sel object:(id)arg; 调用start方法开始执行操作 - (void)start;
创建NSBlockOperation对象
+ (id)blockOperationWithBlock:(void (^)(void))block;
通过addExecutionBlock:方法添加更多的操作
- (void)addExecutionBlock:(void (^)(void))block;
添加操作到NSOperationQueue中
- (void)addOperation:(NSOperation *)op; - (void)addOperationWithBlock:(void (^)(void))block;
一旦执行操作,就会调用target的sel方法
主队列
添加到主队列的操作,最终都执行在主线程上
[NSOperationQueue mainQueue]
当前队列
获取当前操作所在的队列
[NSOperationQueue currentQueue]
最大并发数的相关方法
- (NSInteger)maxConcurrentOperationCount; - (void)setMaxConcurrentOperationCount:(NSInteger)cnt;
取消队列的所有操作
- (void)cancelAllOperations;
提示:也可以调用NSOperation的- (void)cancel方法取消单个操作
暂停和恢复队列
- (void)setSuspended:(BOOL)b; // YES代表暂停队列,NO代表恢复队列 - (BOOL)isSuspended;
设置NSOperation在queue中的优先级,可以改变操作的执行优先级
- (NSOperationQueuePriority)queuePriority; - (void)setQueuePriority:(NSOperationQueuePriority)p;
可以监听一个操作的执行完毕
- (void (^)(void))completionBlock; - (void)setCompletionBlock:(void (^)(void))block;
NSOperation之间可以设置依赖来保证执行顺序
比如一定要让操作A执行完后,才能执行操作B,可以这么写
[operationB addDependency:operationA]; // 操作B依赖于操作A
GCD中两个核心的概念。队列和任务,GCD中是怎么实现的。首先是创建队列,然后定制任务。最后是将任务添加至队列。
然后这个里面就有很多概念了。队列中有串行队列,并行队列,主队列,全局队列。其中要求重点掌握的就是主队列和全局队列,其实主队列本质上就是一个串行队列,全局队列就是一个并行队列。
任务的话,有同步任务和异步任务。
任务之间的依赖可以使用同步任务的方式和barrier(阻塞)来执行。
最后是线程间通讯,不管同步还是异步是不是最后都要回到主队列中去更新数据或者刷新UI显示。是不是dispatch_sync(dispatch_get_main_queue).
然后GCD中还有一些小的知识点就是
主队列,同步执行会出现死锁!
GCD中一次性执行代码!有一个非常重要的应用场景就是单例!
另外一个知识点就是延迟操作。Dispatch_after
将操作(异步)添加到队列(全局的并发队列)。
NSOperation的使用是不是更加面象对象。NSOperation是一个抽象的类,使用的是他的子类。
取消和暂停都会把正在执行的任务先执行完毕后,才会取消或者暂停队列中的任务。
然后还有一个最大并发数,GCD中我们能控制线程数吗?不能,GCD中会自动帮我们管理线程。需要注意的就是最大并发数并不是线程数,我们可以通过最大并发数来控制线程数。
NSoperation中也可以实现操作依赖,GCD中实现操作依赖的方式有什么?
同步和阻塞
这个和GCD中有不同的就是NSOperation可以跨队列设置操作间的依赖。
github地址: https://github.com/FuThD