一个任务通常就是一个程序,每个运行中的程序通常就是一个进程。也就是说所有运行中的任务通常对应一个进程。我们通常会感觉到cpu会同时执行多个任务,但是事实上每一时刻cpu只能执行一个任务。cpu通过时间片轮转等调度算法,快速地在各个进程之间进行切换,以至于在我们看来能同时并发执行多个任务。
线程NSThread是一个轻量级的进程,线程是进程的组成部分,一个进程可以拥有多个线程,线程在程序中是独立的、并发的执行流。当一个进程被初始化的时候,就会创建一个主线程。线程是独立的,是抢占式的,它在执行的时候并不知道其他线程的存在。总结来说:操作系统可以执行多个任务,每个任务都是一个进程,每个进程可以执行多个任务,每个任务都是一条线程。
我们把一些耗时的操作用多线程的方式操作,开一个子线程来完成这些耗时操作,以避免因为耗时而阻塞主线程。增强用户体验。线程能共享内存,这是进程不能的
iOS中提供了三种多线程编程技术抽象程度由低到高分别是:
1>NSThread
2>CGD
3>NSOperation
NSThread简便但是使用比NSOperation复杂,需要对他进行管理(不常用)(底层oc写的)。NSThread需要管理线程的安全、生命周期。
CGD性能最好(常用)(底层C写的),它能充分利用cpu的多核。
NSOperation更加面向对象,更加方便理解。NSOperation是一个抽象类,我们通常不直接使用它,而是使用它的子类(常用)(底层oc写的)
创建NSThread的两种方法:
1、(id)initWithTarget:selector:object://用这种方法创建需要调用start才会启动线程。
2、-(void)detachNewThreadSelector:toTarget:withObject://用着中方法创建线程不用调用start方法,它创建并启动。
【NSThread currentThread】//获取当前的线程
setName设置线程的名字
当线程创建的时候处于新建状态,当调用start的时候处于就绪状态。
线程终止的三种方式:
1、线程执行完后正常结束
2、线程执行过程中遇到错误异常结束
3、调用NSThread的exit方法退出
NSThread并没有一个方法来终止某个子线程,虽然NSThread提供了cancel方法,但是它只是改变子项成的状态,设置isCancelled的值
如果主线程想要终止某一子线程,课以向子线程发送一个信号,在子线程中判断是否收到这个信号如果收到就调用exit方法。
//提交同步任务给主队列(不能这么用,因为它会与主线程相互等待,使得程序不能继续往下执行)
dispatch_sync(mainQueue, ^{
NSLog(@"dddd-%@",[NSThread currentThread]);
});
//创建队列
NSOperationQueue *operationQueue = [[NSOperationQueue alloc]init];
//创建任务
//方式1
/*
NSBlockOperation *blockOption = [NSBlockOperation blockOperationWithBlock:^{
NSLog(@"aaa--%@",[NSThread currentThread]);
}];
//将任务添加到队列中
[operationQueue addOperation:blockOption];//立即执行,会开启一条线程
*/
//方式2
/*
NSInvocationOperation *invocationOption = [[NSInvocationOperation alloc]initWithTarget:self selector:@selector(work) object:nil];
[operationQueue addOperation:invocationOption];
*/
/*
NSBlockOperation *option = [NSBlockOperation blockOperationWithBlock:^{
NSLog(@"aaa--%@",[NSThread currentThread]);
}];
[option start];//马上执行(它不会开启一个线程,会放入当前线程中执行)不用
*/
//设置在某一段时间并发数量的最大值
[operationQueue setMaxConcurrentOperationCount:10];
/*
//快捷开启子线程
[operationQueue addOperationWithBlock:^{
NSLog(@"work-- %@",[NSThread currentThread]);
}];
*/
/*
//为线程排序使用依赖关系
//顺序1,2,3;依赖关系为3依赖2,2依赖1
NSBlockOperation *blockOption1 = [NSBlockOperation blockOperationWithBlock:^{
NSLog(@"aaa--%@",[NSThread currentThread]);
}];
NSBlockOperation *blockOption2 = [NSBlockOperation blockOperationWithBlock:^{
NSLog(@"bbb--%@",[NSThread currentThread]);
}];
NSBlockOperation *blockOption3 = [NSBlockOperation blockOperationWithBlock:^{
NSLog(@"ccc--%@",[NSThread currentThread]);
}];
[blockOption3 addDependency:blockOption2];
[blockOption2 addDependency:blockOption1];
[operationQueue addOperation:blockOption1];
[operationQueue addOperation:blockOption3];
[operationQueue addOperation:blockOption2];
*/
/*
NSURL *url = [NSURL URLWithString:@""];
UIImage *img = [[UIImage alloc]initWithData: [NSData dataWithContentsOfURL:url]];
//返回抓线程刷新UI
[[NSOperationQueue mainQueue]addOperationWithBlock:^{
NSLog(@"刷新UI");
}];
*/
myOperation *operation = [[myOperation alloc]init];
//_imgview.image = operation.img;强指针在myOperation改变img的值,在当前controller中也改变
[operation setShouldReturnImg:^(UIImage *img) {
//用img刷新UI
}];
[operationQueue addOperation:operation];
//取消队列中所有任务
[operationQueue cancelAllOperations];
operationQueue.suspended = YES;//表示暂停
operationQueue.suspended = NO;//表示恢复
}
-(void)work{
NSLog(@"bbb--%@",[NSThread currentThread]);
}
初始化两个队列
_srial = dispatch_queue_create("srial", DISPATCH_QUEUE_SERIAL);//串行队列
_concurrent = dispatch_queue_create("concurrent", DISPATCH_QUEUE_CONCURRENT);//串行队列
//提交任务
dispatch_async(_concurrent, ^{
//要执行的任务
NSLog(@"aaa %@",[NSThread currentThread]);
});//提交异步任务
dispatch_sync(_srial, ^{
NSLog(@"bbb %@",[NSThread currentThread]);
});//提交同步任务
*/
dispatch_queue_t globleQueue = dispatch_get_global_queue(QOS_CLASS_USER_INITIATED, 0);//第二个参数用于扩展
//提交异步任务给全局并发队列
dispatch_async(globleQueue, ^{
NSLog(@"aaa--%@",[NSThread currentThread]);
});//开子线程
//提交同步任务给全局并发队列
dispatch_sync(globleQueue, ^{
NSLog(@"bbb--%@",[NSThread currentThread]);
});//不开子线程
dispatch_queue_t mainQueue = dispatch_get_main_queue();
//提交异步任务给主队列
dispatch_async(mainQueue, ^{
NSLog(@"ccc-%@",[NSThread currentThread]);
});//不开子线程
//提交同步任务给主队列(不能这么用,因为它会与主线程相互等待,使得程序不能继续往下执行)
dispatch_sync(mainQueue, ^{
NSLog(@"dddd-%@",[NSThread currentThread]);
});
//队列组
/*
网络请求
1>用户上传头像到服务器(上行)
2>更新用户信息(下行)
如果开两个子线程,那么久不能保证在更新头像之后,更新数据,如果用同步,那么久会影响到主线程
解决方法有两个:
*/
//解决方法1
dispatch_async(dispatch_get_global_queue(QOS_CLASS_DEFAULT, 0), ^{
NSLog(@"用户上传头像");
dispatch_async(dispatch_get_main_queue(), ^{
dispatch_async(dispatch_get_global_queue(QOS_CLASS_DEFAULT, 0), ^{
NSLog(@"更新用户信息");
});
});
});
//解决方法2使用队列组
/*组包含队列,队列包含任务,队列组使得线程拥有某一顺序完成,但是它还是异步的*/
dispatch_group_t group = dispatch_group_create();
dispatch_queue_t queue = dispatch_get_global_queue(QOS_CLASS_DEFAULT, 0);
dispatch_group_async(group, queue, ^{
//这样就会总是按下面的顺序完成
dispatch_async(queue, ^{
NSLog(@"用户上传图片");
});
dispatch_async(queue, ^{
NSLog(@"更新用户信息");
});
//更新用户信息后会发出通知
dispatch_group_notify(group, queue, ^{
NSLog(@"加载完毕");
});
});
}