进程
1.正在进行的一个过程或任务,负责任务执行的是cpu。
2.每个进程之间是独立的,每个进程都运行在独立的内存空间内,并拥有独立运行所需的全部资源。
线程
1.程序运行时的最小单位,是进程的实际运作单位。
2.进程想要执行任务必须至少有一个线程。在应用程序启动时,系统会默认开启一个线程,即主线程。
进程和线程的关系
1.线程在进程下进行
2.一个进程可以包含多个线程
3.同一个进程内不同的线程间数据容易共享
4.进程是用内存地址可以上锁,即一个线程使用共享内存时,其他线程必须等待其结束,才能使用。(互斥锁)
5.进程使用的内存地址也可以限定使用,即当前只允许2 人访问,第三人需要等待有人结束访问后再进行访问。(信号量)
6.一个程序有多个进程,一个进程可以有多个线程,但每个进程至少要有一个线程。
多线程
1.多条线程并发执行,cpu快速的在多条线程之间调度。 如果cpu调度线程时间足够的快,就造成了多线程并发的假象。
2.如果线程非常多,也会大量消耗cpu资源。
3.多线程可以提高程序的执行效率,能适当提高资源的利用率。
4.如果开启大量的线程会占用内存空间,降低程序性能。
队列
串行队列
同一时间内,队列中只能执行一个任务,当前任务结束后才能执行下一个任务。
并发队列
同时允许多个任务并发执行。
iOS中的多线程
GCD
1.获取主线程
dispatch_queue_t main_queue = dispatch_get_main();
2.线程延时
/**
DISPATCH_TIME_NOW : 现在
DISPATCH_TIME_FOREVER : 永远超时
NSEC_PER_SEC : 秒 (1000,000,000 纳秒 = 1秒) 可精确到纳秒级,eg. 0.1 * NSEC_PER_SEC 是0.1 * 1000,000,000 = 100,000,000 纳秒 = 0.1秒 以下算法雷同。
NSEC_PER_MSEC : 毫秒 (1000,000 纳秒 = 1 毫秒)可精确到毫秒级
USEC_PER_SEC : 秒 (1000000微秒 = 1秒) 可精确到微秒级
NSEC_PER_USEC : 微秒 (1000纳秒 = 1 微秒) 可精确到纳秒级
*/
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, 3 * NSEC_PER_SEC), main_queue, ^{
NSLog(@"哈哈");
})
3.只执行一次,常用作单例模式
static dispatch_once_t once;
dispatch_once(&once, ^{
// 只实例化一次
personModel = [[self alloc] init];
});
4.线程组,即等待一组任务完成后继续执行下一步,常被应用在图片上传
// 开启全集并发线程,DISPATCH_QUEUE_PRIORITY_DEFAULT 是线程等级, 0 是flag,备用字段,通常设置0
dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
dispatch_group_t group = dispatch_group_create();
dispatch_group_async(group, queue, ^{
// 进行操作1
});
dispatch_group_async(group, queue, ^{
// 进行操作2
});
dispatch_group_async(group, queue, ^{
// 进行操作3
});
dispatch_group_notify(group, queue, ^{
// 操作1。2。3 执行完毕 进行 下一步操作
});
// 超时等待,即设置一个最长等待时常,超过时间后 调起 notify block
dispatch_group_wait(group, DISPATCH_TIME_FOREVER);
5.信号量,设置最大并发线程数,设置数大于1时顺序不能保证
//创建信号量, 2为设置最大并发线程
dispatch_semaphore_t semaphore = dispatch_semaphore_create(2);
for (int i = 0; i < 5; i++) {
// 创建异步线程
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
// 信号量的等待时长,这里设置为一直等待,当信号量小于0 时一直等待,如果大于1则进入且降低信号量即-1
dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER);
// 睡眠2秒
sleep(2);
// po 出当前线程, 显示log
NSLog(@"%@", [NSThread currentThread]);
// 标记信号量 + 1
dispatch_semaphore_signal(semaphore);
});
}
for (int i = 0; i < 5; i++) {
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER);
sleep(2);
NSLog(@"%@", [NSThread currentThread]);
dispatch_semaphore_signal(semaphore);
});
}
NSOPeration
NSOperation是基于GCD的抽象基类。
NSOperation可以跨队列设置依赖关系
NSOperation面向对象,支持KVO,可以检测operation是否正在执行,是否结束或者取消
NSOperation实体子类有两个,NSBlockOperation 和 NSInvocationOperation
// 初始化 方法实例
NSInvocationOperation *invoOperation = [[NSInvocationOperation alloc] initWithTarget:self selector:@selector(haha:) object:nil];
[invoOperation start];
// 初始化 block块 实例
NSBlockOperation *blockOpertaion = [NSBlockOperation blockOperationWithBlock:^{
NSLog(@"ni hao ");
}];
// 继续添加线程
blockOperation add
[blockOpertaion start];
// 以下为 依赖关系
// 获取 主线程
NSOperationQueue *main_Operation = [NSOperationQueue mainQueue];
// 创建 各种线程
NSOperation *person_a = [NSBlockOperation blockOperationWithBlock:^{
NSLog(@"我是 神秘人 A");
}];
NSOperation *person_b = [NSBlockOperation blockOperationWithBlock:^{
NSLog(@"我是 神秘人 B");
}];
NSOperation *person_c = [NSBlockOperation blockOperationWithBlock:^{
NSLog(@"我是 神秘人 C");
}];
// 添加依赖关系, A以来 B和C ,相当于 A要在 B C 之后才能执行任务
[person_a addDependency:person_b];
[person_a addDependency:person_c];
//添加到 主线程中 查看顺序
[main_Operation addOperation:person_a];
[main_Operation addOperation:person_b];
[main_Operation addOperation:person_c];
NSThread
NSThread使用比较简单,可以静态获取线程信息
// 获取主线程
NSThread *thread = [NSThread mainThread];
// 判断是否开启了多线程
BOOL isOpenThread = [NSThread isMultiThreaded];
// 获取当前线程
NSThread *currentThread = [NSThread currentThread];
// 当前线程睡眠 时间(s) 10秒钟
[NSThread sleepForTimeInterval:10];
// 睡眠到指定时间 , 以下为当前时间往后延10秒钟
[NSThread sleepUntilDate:[NSDate dateWithTimeIntervalSinceNow:10]];
// 退出当前线程 , 禁止在主线程使用
//[NSThread exit];
// 初始化线程对象 实例化对象
/*
qualityOfService 线程的优先级
NSQualityOfServiceUserInteractive 最高级别,用于UI交互,点击事件,绘制图形等
NSQualityOfServiceUserInitiated = 次高级别,用于执行立即返回的任务
NSQualityOfServiceUtility 普通级别,不需要立即返回的任务
NSQualityOfServiceBackground 后台级别,完全不紧急的任务
NSQualityOfServiceDefault 默认级别
*/
NSLog(@"%@", [NSThread currentThread]);
NSThread *asynThread = [[NSThread alloc] initWithTarget:self selector:@selector(hello) object:nil];
// 设置 线程实例化对象的 优先级别,默认为 默认级别
asynThread.qualityOfService = NSQualityOfServiceDefault;
// 开始线程
[asynThread start];
// 也可以快速创建线程
[NSThread detachNewThreadSelector:@selector(hello) toTarget:self withObject:nil];
__weak typeof(self) weakSelf = self;
[NSThread detachNewThreadWithBlock:^{
// po 出当前线程
NSLog(@"%@", [NSThread currentThread]);
// 回到主线程
[weakSelf performSelectorOnMainThread:@selector(hello) withObject:nil waitUntilDone:NO];
}];
// 还有一些 创建线程的方法
// 3 秒后执行 hello 方法 , 在当前线程
[self performSelector:@selector(hello) withObject:nil afterDelay:3];
// 后台异步执行
[self performSelectorInBackground:@selector(hello) withObject:nil];
// 在主线程上执行 hello 方法
[self performSelectorOnMainThread:@selector(hello) withObject:nil waitUntilDone:NO];
// 在 指定的 asynThread 线程上执行 hello方法 *** 注意避免在子线程中执行 ui交互
[self performSelector:@selector(hello) onThread:asynThread withObject:nil waitUntilDone:NO];