IOS多线程
来源:互联网 发布:查看网络连接命令 编辑:程序博客网 时间:2024/06/17 13:12
(最近想总结下学过的东西,也算是正式步入码农之路了,如有错误之处,还请指正。)
1、先了解一下进程和线程的概念。
进程:一个运行中的程序,程序本身不是一个进程,它只是存放在磁盘中的代码块而已,一旦被读取到内存中运行,它就成了一个进程。比如:电脑运行的QQ,WORD等都是一个进程。
线程:一个进程可以包含多个线程,比如:在QQ中刷朋友圈时,QQ还会接收消息。在word中编辑时,它还会执行保存等各种操作。
耗时操作:1.大量运算 2.各种网络请求 3.加载大文件4.睡眠代码
耗时的操作不能放在主线程,因为这样会导致渲染界面代码执行不及时,出现界面堵塞状态,导致用户体验下降。
在IOS中修改界面的操作不能放在子线程中,如果放在子线程,因为子线程是一般处理耗时的操作,修改页面的代码要等到所有耗时的操作执行完之后才能看到效果,界面更新不及时。
2、创建线程的方法
(1)NSThread
(2)GCD :通过block开启线程 更底层 更高效代码简洁
(3)NSOperation :可以灵活控制线程之间的关系 可以设置并发的线程数量
3、具体实现代码
(1)NSTread
- (IBAction)clicked:(id)sender
{
// [self run];
//开启新的线程去执行run方法
[NSThread detachNewThreadSelector:@selector(run) toTarget:self withObject:nil];
UIView *v = [[UIViewalloc]initWithFrame:CGRectMake(100,100, 100, 100)];
v.backgroundColor = [UIColorredColor];
[self.viewaddSubview:v];
NSLog(@"我的所有的代码都执行完了");
}
-(void)run
{
for (int i=0; i<5; i++)
{
[NSThread sleepForTimeInterval:1];
UIView *v = [[UIViewalloc]initWithFrame:CGRectMake(100, i*100,100, 60)];
v.backgroundColor = [UIColorgreenColor];
//从子线程回到主线程的方法
[self performSelectorOnMainThread:@selector(updateUI:)withObject:v waitUntilDone:NO];
}
}
-(void)updateUI:(UIView *)v
{
[self.viewaddSubview:v];
//如果是其它的控件就要添加刷新显示
//[label setNeedsLayout];//刷新子控件显示
//[label setNeedsDisplay];//刷新自身显示
}
(2)GCD
(2)GCD
-(void)viewDidLoad
{
// 线程队列
// 并行队列:队列中的线程同时执行
// 串行队列:队列中的线程依次执行
// 开启子线程获取系统提供的线程队列(并行队列)
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT,0), ^{
NSLog(@"子线程1开始");
[NSThread sleepForTimeInterval:2];
NSLog(@"子线程1结束");
});
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
NSLog(@"子线程2开始");
[NSThread sleepForTimeInterval:2];
NSLog(@"子线程2结束");
///创建串行线程队列
dispatch_queue_t myQueue =dispatch_queue_create("myQueue",NULL);
dispatch_async(myQueue, ^{
NSLog(@"一号线程开始");
[NSThread sleepForTimeInterval:1];
NSLog(@"一号线程结束");
});
dispatch_async(myQueue, ^{
NSLog(@"二号线程开始");
[NSThread sleepForTimeInterval:1];
NSLog(@"二号线程结束");
//从子线程回到主线程
dispatch_async(dispatch_get_main_queue(), ^{
NSLog(@"这里回到了主线程");
});
});
}
输出结果:
2015-04-27 09:36:01.930 GCD[885:43297] 一号线程开始
2015-04-27 09:36:01.930 GCD[885:43296] 子线程1开始
2015-04-27 09:36:01.930 GCD[885:43295] 子线程2开始
2015-04-27 09:36:02.936 GCD[885:43297] 一号线程结束
2015-04-27 09:36:02.936 GCD[885:43297] 二号线程开始
2015-04-27 09:36:03.936 GCD[885:43296] 子线程1结束
2015-04-27 09:36:03.936 GCD[885:43295] 子线程2结束
2015-04-27 09:36:03.936 GCD[885:43297] 二号线程结束
2015-04-27 09:36:03.937 GCD[885:43214] 这里回到了主线程
====================================
(3)NSOperation
NSOperation* op1 =[[NSInvocationOperationalloc]initWithTarget:selfselector:@selector(run)object:nil];
NSOperation* op2 =[NSBlockOperationblockOperationWithBlock:^{
for (int i =0; i< 5; i ++)
{
[NSThread sleepForTimeInterval:2];
NSLog(@"线程2");
}
} ];
// [op2 start]; 开启线程
//添加op1的依赖
[op1 addDependency:op2];
NSOperationQueue* myQueue = [[NSOperationQueuealloc]init];
//设置最大的线程并行数量如果为1的话就相当于串行
[myQueue setMaxConcurrentOperationCount:1];
//添加到队列开启线程
[myQueue addOperation:op1];
[myQueue addOperation:op2];
输出结果:
2015-04-27 09:44:05.493 NSOperation[993:49305] 线程一 0
2015-04-27 09:44:07.499 NSOperation[993:49305] 线程一 1
2015-04-27 09:44:09.505 NSOperation[993:49305] 线程一 2
2015-04-27 09:44:11.509 NSOperation[993:49305] 线程一 3
2015-04-27 09:44:13.511 NSOperation[993:49305] 线程一 4
=========================================
// 线程同步方式:1.同步代码块
// 参数要一个对象必须同一个对象对象内部有一个锁的表示
// @synchronized(self){
// 2.使用NSLock对象
// [self.myLock lock];
// 3.NSCondition对象
self.totalCount =100;
self.myLock = [[NSLockalloc] init];
self.myCondition = [[NSConditionalloc] init];
NSThread* t1 = [[NSThreadalloc]initWithTarget:selfselector:@selector(salesChicket)object:nil];
[t1 setName:@"窗口一"];
[t1 start];
NSThread* t2 = [[NSThreadalloc]initWithTarget:selfselector:@selector(salesChicket)object:nil];
[t2 setName:@"窗口二"];
[t2 start];
-(void)salesChicket
{
NSString* name = [NSThreadcurrentThread].name;
//开启同步
//线程同步方式:1.同步代码块
// 2.使用NSLock对象
// [self.myLock lock];
// 3.NSCondition对象
//参数要一个对象必须同一个对象对象内部有一个锁的表示
// @synchronized(self)//使同步
// {
//[self.myLock lock];
[self.myConditionlock];
NSLog(@"%@开始卖%d号票",name,self.salesCount+1);
[NSThread sleepForTimeInterval:.5];
self.salesCount++;
NSLog(@"%@卖票结束卖了%d号票还剩%d张",name,self.salesCount,self.totalCount-self.salesCount);
//}
//[self.myLock unlock];
[self.myConditionunlock];
- ios多线程
- iOS多线程
- iOS多线程
- iOS多线程
- 多线程ios
- IOS 多线程
- ios多线程
- ios 多线程
- IOS多线程
- IOS多线程
- iOS多线程
- iOS多线程
- ios 多线程
- iOS多线程
- IOS多线程
- ios多线程
- iOS 多线程
- iOS 多线程
- 因缓存机制产生的数据实时性问题
- HTML5 - canvas标签
- iOS程序打包上传及新版本更新
- Tesseract3 训练(转载整合) 3.0.1
- Gradle 1.12用户指南翻译——第二十二章. 标准的 Gradle 插件
- IOS多线程
- HTML5 - 智能表单
- iOS开发UI篇—在UItableview中实现加载更多功能
- js随笔1
- 海思SDK安装时,无法运行sdk.unpack
- 提高第6课时,实践1,k次方之和
- switch在打包环境是的无效
- 一个bug引发的感想
- windows清除端口占用