iOS_多线程(一)
– 充分发挥多核处理器优势,将不同线程任务分配给不同的处理器,真正进入“并行运算”状态
– 共享资源的“争夺”
– 从第二个线程开始都是512KB
– 这些数值不能通过编译器开关或线程API函数更改
iOS的三种多线程技术
以下两点是苹果专门开发的“并发”技术,使得程序员可以不再去 关心线程的具体使用问题
• NSThread:
– 优点:NSThread 比其他两个轻量级,使用简单
– 缺点:需要自己管理线程的生命周期、线程同步、加锁、睡眠以 及唤醒等。线程同步对数据的加锁会有一定的系统开销
• NSOperation:
– 不需要关心线程管理,数据同步的事情,可以把精力放在自己需要执行的操作上
– NSOperation是面向对象的 • GCD:
#import "ViewController.h" @interface ViewController () {NSUInteger _tickets;//总票数 } @property (weak, nonatomic) IBOutlet UITextView *textView; @end @implementation ViewController - (void)viewDidLoad {[super viewDidLoad];self.textView.text = @"";self.textView.layoutManager.allowsNonContiguousLayout = NO;//初始化总票数_tickets = 20;//创建线程,并启动线程//1.售票线程1NSThread *thread1 = [[NSThread alloc]initWithTarget:self selector:@selector(threadSellMethod) object:nil];//设置线程的名字[thread1 setName:@"售票线程-1"];//启动线程 [thread1 start];//2.售票线程2NSThread *thread2 = [[NSThread alloc]initWithTarget:self selector:@selector(threadSellMethod) object:nil];//设置线程的名字[thread2 setName:@"售票线程-2"];//启动线程 [thread2 start]; } /*** 更新UI*/ -(void)appendTextView:(NSString *)text {//1.获取textView中已有的内容NSMutableString *string = [[NSMutableString alloc]initWithString:self.textView.text];NSRange range = NSMakeRange(string.length, 1);//2.追加新的内容并显示[string appendString:[NSString stringWithFormat:@"%@\n",text]];[self.textView setText:string];//3.滚动视图 [self.textView scrollRangeToVisible:range]; } /*** 线程执行的方法-售票*/ -(void)threadSellMethod {while (YES){//判断是否有剩余票数if (_tickets > 0){//1.更新UINSString *info = [NSString stringWithFormat:@"总票数:%ld,当前线程:%@",_tickets,[[NSThread currentThread]name]];[self performSelectorOnMainThread:@selector(appendTextView:) withObject:info waitUntilDone:YES];//2.售票_tickets--;//3.模拟休息时间if ([[[NSThread currentThread]name] isEqualToString:@"售票进程-1"]){[NSThread sleepForTimeInterval:0.3f];}else{[NSThread sleepForTimeInterval:0.2f];}}else{//1.更新UINSString *info = [NSString stringWithFormat:@"已无剩余票数,当前线程:%@",[[NSThread currentThread]name] ];[self performSelectorOnMainThread:@selector(appendTextView:) withObject:info waitUntilDone:YES];//2.退出线程break;}} } @end
//NSThread的实例方法创建多线程//1.售票线程1NSThread *thread1 = [[NSThread alloc]initWithTarget:self selector:@selector(threadSellMethod) object:nil];//设置线程的名字[thread1 setName:@"售票线程-1"];//启动线程 [thread1 start];//等效于://NSThread的类方法创建多线程[NSThread detachNewThreadSelector:@selector(threadSellMethod) toTarget:self withObject:@"售票线程-1"];
#import "ViewController.h" @interface ViewController () {NSUInteger _tickets;//总票数 } @property (weak, nonatomic) IBOutlet UITextView *textView; //@property(strong,nonatomic)NSLock *lock; //@property(strong,nonatomic)NSCondition *condition; @end@implementation ViewController- (void)viewDidLoad {[super viewDidLoad];self.textView.text = @"";self.textView.layoutManager.allowsNonContiguousLayout = NO;//初始化总票数_tickets = 20;//创建线程锁 // self.lock = [[NSLock alloc]init]; // self.condition = [[NSCondition alloc]init];//创建线程,并启动线程//1.售票线程1NSThread *thread1 = [[NSThread alloc]initWithTarget:self selector:@selector(threadSellMethod) object:nil];//设置线程的名字[thread1 setName:@"售票线程-1"];//启动线程 [thread1 start];//2.售票线程2NSThread *thread2 = [[NSThread alloc]initWithTarget:self selector:@selector(threadSellMethod) object:nil];//设置线程的名字[thread2 setName:@"售票线程-2"];//启动线程 [thread2 start]; }/*** 更新UI*/ -(void)appendTextView:(NSString *)text {//1.获取textView中已有的内容NSMutableString *string = [[NSMutableString alloc]initWithString:self.textView.text];NSRange range = NSMakeRange(string.length, 1);//2.追加新的内容并显示[string appendString:[NSString stringWithFormat:@"%@\n",text]];[self.textView setText:string];//3.滚动视图 [self.textView scrollRangeToVisible:range]; } /*** 线程执行的方法-售票*/ -(void)threadSellMethod {while (YES){//判断是否有剩余票数if (_tickets > 0){/*** 加锁应该是在有竞争资源的地方*///访问竞争资源前进行加锁 // [self.lock lock]; // [self.condition lock];/*** 需要同步的代码块放入synchronized块中*/@synchronized(self){@autoreleasepool{//1.更新UINSString *info = [NSString stringWithFormat:@"总票数:%ld,当前线程:%@",_tickets,[[NSThread currentThread]name]];[self performSelectorOnMainThread:@selector(appendTextView:) withObject:info waitUntilDone:YES];//2.售票_tickets--;}}//访问完竞争资源后进行解锁 // [self.condition unlock]; // [self.lock unlock];//3.模拟休息时间if ([[[NSThread currentThread]name] isEqualToString:@"售票进程-1"]){[NSThread sleepForTimeInterval:0.3f];}else{[NSThread sleepForTimeInterval:0.2f];}}else{//1.更新UINSString *info = [NSString stringWithFormat:@"已无剩余票数,当前线程:%@",[[NSThread currentThread]name] ];[self performSelectorOnMainThread:@selector(appendTextView:) withObject:info waitUntilDone:YES];//2.退出线程break;}} } @end
运行结果如图:
现在再来看运行结果,发现上个案例中出现的问题已经解决了,每个只会出现一次。
再来看程序的代码部分,案例中使用了给出了三个解决同步安全问题的办法,代码中标出的蓝色部分是NSLock、NSCondition的用法,案例中使用的是@synchronized同步块。解决同步安全的逻辑思路“加锁”->"修改"->"解锁"。当当前线程正在使用竞争资源时,阻挡掉其他线程对竞争资源的访问。
在程序中还用到了内存管理的自动释放池。
• Objective-C可以凭借@autoreleasepool使用内存资源,并需要时回收资源
- (void)setMaxConcurrentOperationCount:(NSInteger)cnt;
在此案例中,不多做解释,直接代码搞起。
第一个案例通过NSInvocationOperation类进行实现
#import "ViewController.h"@interface ViewController () {NSUInteger _tickets; } @property (weak, nonatomic) IBOutlet UITextView *textView;@end@implementation ViewController- (void)viewDidLoad {[super viewDidLoad];//初始化票数_tickets = 30;//设置textViewself.textView.text = @"";//创建NSOperationNSInvocationOperation *operation1 = [[NSInvocationOperation alloc]initWithTarget:self selector:@selector(operationSaleMethod:) object:@"售票线程-1"];NSInvocationOperation *operation2 = [[NSInvocationOperation alloc]initWithTarget:self selector:@selector(operationSaleMethod:) object:@"售票线程-2"];//创建NSOperationQueue队列NSOperationQueue *queue = [[NSOperationQueue alloc]init]; //为operation1添加依赖,只有当operation2执行完毕时,operation1才能执行。 [operation1 addDependency:operation2];//将operation加入到队列 [queue addOperation:operation1];[queue addOperation:operation2]; }#pragma mark - 更新UI -(void)appendTextView:(NSString *)text {//1.先获取原先的内容NSMutableString *str = [[NSMutableString alloc]initWithString:self.textView.text];NSRange range = NSMakeRange(str.length, 1);//2.追加新的内容[str appendString:[NSString stringWithFormat:@"%@\n",text]];[self.textView setText:str];//3.滚动textView [self.textView scrollRangeToVisible:range]; } #pragma mark - 线程调用的方法 -(void)operationSaleMethod:(NSString *)name {while (YES){//判断剩余票数if (_tickets > 0){@synchronized(self){NSString *info = [NSString stringWithFormat:@"总的票数:%ld,当前线程:%@",_tickets,name];[[NSOperationQueue mainQueue]addOperationWithBlock:^{[self appendTextView:info];}];//卖票_tickets--;}if ([name isEqualToString:@"售票线程-1"]){//线程休眠[NSThread sleepForTimeInterval:0.3f];}else{[NSThread sleepForTimeInterval:0.2f];}}else{//更新UINSString *info = [NSString stringWithFormat:@"已无剩余票数,当前线程:%@",name];[[NSOperationQueue mainQueue]addOperationWithBlock:^{[self appendTextView:info];}]; break;}} } @end
案例2:通过NSBlockOperation进行实现
#import "ViewController.h"@interface ViewController () {NSInteger _tickets; } @property (weak, nonatomic) IBOutlet UITextView *textView;@end@implementation ViewController- (void)viewDidLoad {[super viewDidLoad];//初始化票数_tickets = 30;//设置textViewself.textView.text = @"";//创建NSOperationQueue队列NSOperationQueue *queue = [[NSOperationQueue alloc]init];//设置线程的并行数量[queue setMaxConcurrentOperationCount:2];//在队列中添加block的operation[queue addOperationWithBlock:^{[self operationSaleMethod:@"售票线程-1"];}];[queue addOperationWithBlock:^{[self operationSaleMethod:@"售票线程-2"];}];NSBlockOperation *operation = [NSBlockOperation blockOperationWithBlock:^{[self operationSaleMethod:@"售票线程-3"];}];//将线程添加到队列中去 [queue addOperation:operation];}#pragma mark - 更新UI -(void)appendTextView:(NSString *)text {//1.先获取原先的内容NSMutableString *str = [[NSMutableString alloc]initWithString:self.textView.text];NSRange range = NSMakeRange(str.length, 1);//2.追加新的内容[str appendString:[NSString stringWithFormat:@"%@\n",text]];[self.textView setText:str];//3.滚动textView [self.textView scrollRangeToVisible:range]; } #pragma mark - 线程调用的方法 -(void)operationSaleMethod:(NSString *)name {while (YES){//判断剩余票数if (_tickets > 0){@synchronized(self){NSString *info = [NSString stringWithFormat:@"总的票数:%ld,当前线程:%@",_tickets,name];[[NSOperationQueue mainQueue]addOperationWithBlock:^{[self appendTextView:info];}];//卖票_tickets--;}if ([name isEqualToString:@"售票线程-1"]){//线程休眠[NSThread sleepForTimeInterval:0.3f];}else{[NSThread sleepForTimeInterval:0.2f];}}else{//更新UINSString *info = [NSString stringWithFormat:@"已无剩余票数,当前线程:%@",name];[[NSOperationQueue mainQueue]addOperationWithBlock:^{[self appendTextView:info];}];break;}} } @end
以上两个案例的运行结果一致,如图:
如果希望当其中一个线程执行完毕之后,再去执行另外一个线程,可以通过依赖来实现。
//为operation1添加依赖,只有当operation2执行完毕时,operation1才能执行。[operation1 addDependency:operation2];
累死啦!!
转载于:https://www.cnblogs.com/xjf125/p/4857658.html
iOS_多线程(一)相关推荐
- IOS_多线程_ASI_AFN_UIWebView
H:/0730/00_多线程4种售票_ViewController.h // // ViewController.h // 卖票 // // Created by apple on 13-7-29. ...
- Java 多线程概述
多线程技术概述 1.线程与进程 进程:内存中运行的应用程序,每个进程都拥有一个独立的内存空间. 线程:是进程中的一个执行路径,共享一个内存空间,线程之间可以自由切换.并发执行,一个进程最少有一个线程, ...
- Java 多线程的基本方式
Java 多线程的基本方式 基础实现两种方式: 通过实现Callable 接口方式(可得到返回值):
- RPC 笔记(08)— socket 通信(多进程多线程服务器)
在上一节中如果并行的客户端连接数超过了默认开启进程的数量,那么后来的客户端请求将会阻塞,为了不阻塞新的客户端,我们可以将进程的单线程改成多线程即可. 服务端代码: import json impo ...
- Python 多线程总结(2)— 线程锁、线程池、线程数量、互斥锁、死锁、线程同步
主要介绍使用 threading 模块创建线程的 3 种方式,分别为: 创建 Thread 实例函数 创建 Thread 实例可调用的类对象 使用 Thread 派生子类的方式 多线程是提高效率的一种 ...
- Python 多线程总结(1)- thread 模块
thread 模块 1. 单线程 首先看下单线程程序运行的例子,如下所示, import timedef loop0():print 'start loop0 begin', time.ctime() ...
- Python多线程调试
有时候程序是多线程的,调试的时候可能跑到别的线程了. 这个时候把thread.start变成threa.run就好了,就会执行完当前线程再执行下一个. for thread in threads:th ...
- python究竟要不要使用多线程
阅读目录 1. 先来看两个例子 2. python虚拟机机制如何控制代码执行? 3. python多线程究竟有没有用? 4. python多进程执行原理 在总结concurrent.futures库之 ...
- Python多线程(3)——Queue模块
Python多线程(3)--Queue模块 Queue模块支持先进先出(FIFO)队列,支持多线程的访问,包括一个主要的类型(Queue)和两个异常类(exception classes). Pyth ...
最新文章
- mxOutlookBarPro中,button是通过for语句动态生成的,如何取得当前单击button的标题呢?...
- PL/SQL Developer下设置“长SQL自己主动换行”
- How to: Display a Gradient Fill
- 【渝粤教育】国家开放大学2018年春季 0273-21T中国现代文学 参考试题
- sublime php快捷键,分享Sublime Text 3快捷键精华版!
- Python自动化测试|如何解决前置模块及数据依赖(二)
- C++笔记-Qt中使用Lambda时[]中的形式
- springboot 控制台输出错误信息_SpringBoot 三招组合拳,手把手教你打出优雅的后端接口...
- JBox - 模态窗口,工具提示和消息 jQuery 插件
- Unity 2018.3.8 f1 个人版的Standard Assets在哪里下载?
- Fast-RTPS初体验
- 设计模式(二)Adapter模式
- 电气领域相关数据集(目标检测,分类图像数据及负荷预测),输电线路图像数据
- 什么才是真正的架构设计
- oracle数据库按日期查询,关于Oracle数据库日期范围查询的两种实现方法详解,oracle详解...
- ios链接xcode跑自动化意外中断?可以用pyautogui试试
- 单点登录 Ucenter 分析
- Mac 双系统bootcamp不能正常卸载windows系统
- 计算机作业我家乡的变化英语作文,我家乡的变化英语作文(精选12篇)
- 自己更换云平台绑定QQ号的方法