iOS多线程-全面总结
- 进程和线程
进程:
进程(Process)是计算机中的程序关于某数据集合上的一次运行活动,是系统进行资源分配和调度的基本单位,是操作系统结构的基础(百度百科)
根据百度百科的解释我们知道进程是系统进行资源分配和调度的基本单位,在手机端一个进程就是一个app
线程
线程,有时被称为轻量级进程(Lightweight Process,LWP),是程序执行流的最小单元。一个标准的线程由线程ID,当前指令指针(PC),寄存器集合和堆栈组成。(百度百科)
根据百度百科我们知道,线程来说其实是进程一个实体
一个进程中至少有一条线程,这条线程我们称为主线程
- iOS中的创建线程和操作线程
- pThread:纯c语言编写,需要自己管理线程
OS X and iOS provide C-based support for creating threads using the POSIX thread API. This technology can actually be used in any type of application (including Cocoa and Cocoa Touch applications) and might be more convenient if you are writing your software for multiple platforms. The POSIX routine you use to create threads is called, appropriately enough, pthread_create.(苹果官方文档)
官方文档上说,这是一个基于C语言的创建和使用线程的API,而且是一个跨平台的API。POSIX:可一直操作系统接口,这个在开发中基本上不使用。如果有用到,可以查看官方文档https://developer.apple.com/library/content/documentation/Cocoa/Conceptual/Multithreading/CreatingThreads/CreatingThreads.html#//apple_ref/doc/uid/10000057i-CH15-SW12
- NSThread:OC封装面向对象,需要自己管理线程释放,相对用起来比较简单
还有一些实用的熟悉和方法比如
currentThread、isMultiThreaded、+ (void)sleepUntilDate:(NSDate *)date;+(void)sleepForTimeInterval:(NSTimeInterval)ti;、+ (void)exit; 等等如果需要查看NSThread.h文件查看
我觉得NSThread来说只是用来创建线程,在当前队列执行,并不能创建队列,控制创建的线程加入哪个队列,所以之后才会有GCD的出现
- GCD:也是基于C语言的API,
CGD里概念:
同步任务:1> 不会开启新线程 2>必须等block离得任务执行完才会返回, 顺序执行
Submits a block object for execution on a dispatch queue and waits until that block completes.
NSLog(@"1");
dispatch_sync(dispatch_get_global_queue(0, 0), ^{
NSLog(@"2");
});
dispatch_sync(dispatch_get_global_queue(0, 0), ^{
NSLog(@"3");
});
dispatch_sync(dispatch_get_global_queue(0, 0), ^{
NSLog(@"4");
});
结果
2018-03-27 23:29:02.297741+0800 Test[942:116200] 1
2018-03-27 23:29:02.297936+0800 Test[942:116200] 2
2018-03-27 23:29:02.298014+0800 Test[942:116200] 3
2018-03-27 23:29:02.298104+0800 Test[942:116200] 4
异步任务:1>可能会开新线程 2>如果加入到并行队列,非顺序执行, 加入串行队列顺序执行 3>将任务block加入指定队列,立即返回,不需要等待任务执行完
``` 异步+并行队列
NSLog(@”1-%@”, [NSThread currentThread]);
dispatch_async(dispatch_get_global_queue(0, 0), ^{
NSLog(@”2-%@”, [NSThread currentThread]);
});
dispatch_async(dispatch_get_global_queue(0, 0), ^{
NSLog(@”3-%@”, [NSThread currentThread]);
});
dispatch_async(dispatch_get_global_queue(0, 0), ^{
NSLog(@”4-%@”, [NSThread currentThread]);
});
打印结果:
1-{number = 1, name = main}
2018-03-27 23:38:01.181646+0800 Test[979:124365] 2-{number = 6, name = (null)}
2018-03-27 23:38:01.181656+0800 Test[979:124369] 4-{number = 8, name = (null)}
2018-03-27 23:38:01.181657+0800 Test[979:124371] 3-{number = 7, name = (null)}
异步+串行队列
NSLog(@”1-%@”, [NSThread currentThread]);
dispatch_async(dispatch_get_main_queue(), ^{
NSLog(@”2-%@”, [NSThread currentThread]);
});
dispatch_async(dispatch_get_main_queue(), ^{
NSLog(@”3-%@”, [NSThread currentThread]);
});
dispatch_async(dispatch_get_main_queue(), ^{
NSLog(@”4-%@”, [NSThread currentThread]);
});
NSLog(@”5-%@”, [NSThread currentThread]);
打印结果:
2018-03-27 23:42:52.072007+0800 Test[1021:129732] 1-{number = 1, name = main}
2018-03-27 23:42:52.072164+0800 Test[1021:129732] 5-{number = 1, name = main}
2018-03-27 23:42:52.074873+0800 Test[1021:129732] 2-{number = 1, name = main}
2018-03-27 23:42:52.075025+0800 Test[1021:129732] 3-{number = 1, name = main}
2018-03-27 23:42:52.075210+0800 Test[1021:129732] 4-{number = 1, name = main}
```
- 并行队列:并发执行队列,需要根据任务的同步性还是异步性决定,是否顺序执行;异步任务+并行队列:非顺序并发执行,同步+并行队列:顺序执行,并发队列的创建方法:
- 1.自定义队列:dispatch_queue_t
dispatch_queue_create(const char *_Nullable label,
dispatch_queue_attr_t _Nullable attr);
- 1.自定义队列:dispatch_queue_t
attr In macOS 10.7 and later or iOS 4.3 and later, specify DISPATCH_QUEUE_SERIAL (or NULL) to create a serial queue or specify DISPATCH_QUEUE_CONCURRENT to create a concurrent queue. In earlier versions, you must specify NULL for this parameter.
那么创建并发队列需要将第二个参数设置为DISPATCH_QUEUE_CONCURRENT
- 2.全局队列:dispatch_get_global_queue(0, 0)
第一个参数,服务质量决定任务执行的优先级
The quality of service you want to give to tasks executed using this queue. Quality-of-service helps determine the priority given to tasks executed by the queue.QOS_CLASS_USER_INTERACTIVE, QOS_CLASS_USER_INITIATED, QOS_CLASS_UTILITY, or QOS_CLASS_BACKGROUND
第二个参数现在还没用到,属于保留参数,设置为0
串行队列:不管异步任务还是同步任务,都是顺序执行
创建串行队列,如上1所述:只需要设置第二个参数为DISPATCH_QUEUE_SERIAL (or NULL) 2.dispatch_get_main_queue()
-
dispatch_group: 将队列添加到队列组里
- 队列组可以添加一个任务到队列并且将队列加入队列组
- dispatch_group_async(dispatch_group_t group,
dispatch_queue_t queue,
dispatch_block_t block); - void
dispatch_group_notify(dispatch_group_t group,
dispatch_queue_t queue,
dispatch_block_t block); // 监听所有队列里的任务都完成后执行block里的任务
-
栅栏函数:栅栏函数的作用是拦住栅栏函数前面正在执行的任务,等待栅栏函数执行完成执行栅栏函数后边的函数
- 栅栏函数使用注意点: 队列必须是自己创建的并发队列;async和sync的区别就是async不会等待任务block执行完返回,sync会等待栅栏函数中的block函数执行完返回
- dispatch_barrier_async(dispatch_queue_t queue, dispatch_block_t block);
- void
dispatch_barrier_sync(dispatch_queue_t queue,
DISPATCH_NOESCAPE dispatch_block_t block);
void
-
延迟执行:
- dispatch_after(dispatch_time_t when,
dispatch_queue_t queue,
dispatch_block_t block);
- dispatch_after(dispatch_time_t when,
-
执行一次函数:应用于单利的创建
- dispatch_once(dispatch_once_t *predicate,
DISPATCH_NOESCAPE dispatch_block_t block);
- dispatch_once(dispatch_once_t *predicate,
-
NSOperation: NSOperation 是一个抽象任务类,不能直接使用,需要实例化两个子类使用,基于GCD的封装,将多线程简单化为队列和任务,使用起来也是很简单的
*它与CGD的区别就是GCD是更底层的封装,在性能上会比NSOperation好点- NSBlockOperation:用一个block的方式初始化一个任务
实例化:
NSBlockOperation *task1 = [NSBlockOperation blockOperationWithBlock:^{
NSLog(@”1-%@”, [NSThread currentThread]);
}]; - NSInvocationOperation:Target-Action的方式初始一个任务
初始化方式:
NSInvocationOperation *task2 = [[NSInvocationOperation alloc] initWithTarget:self selector:@selector(task) object:nil]; - NSOperationQueue :任务运行队列
init方式初始:初始化一个并行队列
NSOperationQueue *queue = [[NSOperationQueue alloc] init];
mianQueue方式获取主队列:获取主队列,是一个串行队列
NSOperationQueue *queue = [NSOperationQueue mainQueue];
- 直接添加任务block到队列
– (void)addOperationWithBlock:(void (^)(void))block API_AVAILABLE(macos(10.6), ios(4.0), watchos(2.0), tvos(9.0)); - 设置并发数:maxConcurrentOperationCount
- 挂起当前队列:suspended
- 设置队列的优先级:qualityOfService
- 取消队列所有任务: cancelAllOperations
- 等待所有队列任务执行完成:
– (void)waitUntilAllOperationsAreFinished;
- 直接添加任务block到队列
- 添加任务依赖:一个任务需要依赖另外一个任务执行完成才能执行
– (void)addDependency:(NSOperation *)op;
*移除依赖关系:
– (void)removeDependency:(NSOperation *)op;
- NSBlockOperation:用一个block的方式初始化一个任务
以上iOS多线程中知识,在此做一个总结,一起共勉!