iOS 多线程NSThread理解与场景示例
NSThread是相对GCD和NSOperationQuene而言,比较轻量级的一种多线程处理方式。
但同时,它的弊端就是需要自己管理线程的生命周期,以及线程同步;而另外两种不需要自己管理。
常见方法介绍:
一、获取当前线程
NSThread *current = [NSThread currentThread];
二、获取主线程
NSThread *main = [NSThread mainThread];
三、NSThread的创建
1 // 初始化线程
2 NSThread *thread = [[NSThread alloc] initWithTarget:self selector:@selector(run:) object:@"aaa"];
3 // 开启线程
4 [thread start];
.静态方法
+ (void)detachNewThreadSelector:(SEL)selector toTarget:(id)target withObject:(id)argument;
[NSThread detachNewThreadSelector:@selector(run:) toTarget:self withObject:@""];
执行完上面代码后会马上启动一条新线程,并且在这条线程上调用self的run方法。
.隐式创建线程
[self performSelectorInBackground:@selector(run:) withObject:@""];
会隐式地创建一条新线程,并且在这条线程上调用self的run方法。
四、暂停当前线程
[NSThread sleepForTimeInterval:2];
NSDate *date = [NSDate dateWithTimeInterval:2 sinceDate:[NSDate date]];
[NSThread sleepUntilDate:date];
上面两种做法都是暂停当前线程2秒
退出线程
[NSThread exit];
五、线程的其他操作
1.在指定线程上执行操作
1 [self performSelector:@selector(run) onThread:thread withObject:nil waitUntilDone:YES];
* 上面代码的意思是在thread这条线程上调用self的run方法
* 最后的YES代表:上面的代码会阻塞,等run方法在thread线程执行完毕后,上面的代码才会通过
2.在主线程上执行操作
[self performSelectorOnMainThread:@selector(run) withObject:nil waitUntilDone:YES];
在主线程调用self的run方法
3.在当前线程执行操作
[self performSelector:@selector(run) withObject:nil];
在当前线程调用self的run方法
场景1:
异步下载一张图片,下载完在UI显示。
代码实现:
//开启子线程下载
[NSThread detachNewThreadSelector:@selector(downloadPic) toTarget:self withObject:nil]; //下载图片
-(void)downloadPic{
NSURL *url = [NSURL URLWithString:@"https://res.wx.qq.com/mpres/htmledition/images/mp_qrcode218877.gif"];
NSData *pic = [NSData dataWithContentsOfURL:url];
UIImage *img = [UIImage imageWithData:pic];
//回到主线程显示
[self performSelectorOnMainThread:@selector(showImg:) withObject:img waitUntilDone:YES];
} -(void)showImg:(UIImage *)image{
//imageView.image = image
NSLog(@"显示 pic");
}
六、多线程安全与加锁
说明:多线程访问同一个资源的时候可能会出现数据错乱等安全问题,解决方法是对必要的代码段进行加锁。
注意:在OC中加互斥锁使用@synchronized(self) {},在swift可以使用objc_sync_enter(self)和objc_sync_exit(self)方法,注意这两个方法必须成对使用,把要加锁的代码放在中间.
场景1:
以售票为例:3个售票员同时售票,票总数为10。
- (void)sailTicket {
NSThread *thread1 = [[NSThread alloc] initWithTarget:self selector:@selector(sale) object:nil];
NSThread *thread2 = [[NSThread alloc] initWithTarget:self selector:@selector(sale) object:nil];
NSThread *thread3 = [[NSThread alloc] initWithTarget:self selector:@selector(sale) object:nil];
thread1.name = @"售票员1";
thread2.name = @"售票员2";
thread3.name = @"售票员3";
[thread1 start];
[thread2 start];
[thread3 start];
}
-(void)sale{
while () {
@synchronized (self) {
for (int i = ; i<; i++) {
//模拟延迟
}
if (_ticketCount>){
_ticketCount--;
NSLog(@"%@卖出了一张票,余票还有%lu",[NSThread currentThread].name,(unsigned long)_ticketCount);
}else{
NSLog(@"票已售完");
break;
}
}
}
}

可以很明显看出,每个售票员都是严格按照从10递减的方式售票,不存在票数忽多忽少的情况。
如果不加锁:

iOS 多线程NSThread理解与场景示例的更多相关文章
- iOS多线程 NSThread/GCD/NSOperationQueue
无论是GCD,NSOperationQueue或是NSThread, 都没有线程安全 在需要同步的时候需要使用NSLock或者它的子类进行加锁同步 "] UTF8String], DISPA ...
- ios多线程NSThread
1.简介: 1.1 iOS有三种多线程编程的技术,分别是: 1..NSThread 2.Cocoa NSOperation (iOS多线程编程之NSOperation和NSOperationQueue ...
- iOS多线程NSThread和GCD
在iOS中啊 其实有多种方法实现多线程 这里只记录两个比较常用的 或者说我比较常用的 一个就是BSThread 另一个就是一听名字就比较霸气的妇孺皆知的GCD 先说一下NSThread吧 这个方式 ...
- iOS 多线程之线程锁Swift-Demo示例总结
线程锁是什么 在前面的文章中总结过多线程,总结了多线程之后,线程锁也是必须要好好总结的东西,这篇文章构思的时候可能写的东西得许多,只能挤时间一点点的慢慢的总结了,知道了线程之后要了解线程锁就得先了解一 ...
- IOS 多线程 NSThread
一个正在运行的应用程序是一个进程,一个进程会默认开启一个主线程,但是在主线程中的操作是串行的,也就是当有多个任务同时需要完成的时候,是按照顺序一个个执行.因此,为了提高效率,会在进程中开启多个线程,每 ...
- IOS 多线程-NSThread 和线程状态
@interface HMViewController () - (IBAction)btnClick; @end @implementation HMViewController - (void)v ...
- iOS多线程的详情使用示例--简进祥
大家都知道,在开发过程中应该尽可能减少用户等待时间,让程序尽可能快的完成运算.可是无论是哪种语言开发的程序最终往往转换成汇编语言进而解释成机器码来执行.但是机器码是按顺序执行的,一个复杂的多步操作只能 ...
- iOS多线程开发
概览 大家都知道,在开发过程中应该尽可能减少用户等待时间,让程序尽可能快的完成运算.可是无论是哪种语言开发的程序最终往往转换成汇编语言进而解释成机器码来执行.但是机器码是按顺序执行的,一个复杂的多步操 ...
- iOS 多线程详解
iOS开发 多线程 概览 机器码是按顺序执行的,一个复杂的多步操作只能一步步按顺序逐个执行.改变这种状况可以从两个角度出发: 对于单核处理器,可以将多个步骤放到不同的线程,这样一来用户完成UI操作后其 ...
随机推荐
- Android Wi-Fi Display(Miracast)介绍
地址:http://blog.csdn.net/innost/article/details/8474683 Android Wi-Fi Display(Miracast)介绍 2012年11月中旬, ...
- C#调用SCL2008 动态库SCL_API_cdecl.dll or SCL_API_Stdcall.dll,提示找不到指定模块
在公司用的联想 ThinkPad T430i,原装配置及系统,开机巨慢.按下开机键到登陆界面超过1分钟,再到桌面这个时间就难说了,多时有超过3分钟,进入桌面还要等待几分钟才能正常操作.新年过来向公司领 ...
- 【翻译】go语言中的map实战
业余时间翻译,水平很差,如有瑕疵,纯属无能. 原文链接 http://blog.golang.org/go-maps-in-action go语言中的map实战 1. 简介 哈希表是计算机科学中最重要 ...
- JavaScript 逗号表达式
逗号表达式的一般形式是:表达式1,表达式2,表达式3……表达式n 逗号表达式的求解过程是:先计算表达式1的值,再计算表达式2的值,……一直计算到表达式n的值.最后整个逗号表达式的值是表达式n的值. ...
- Spring ---annotation (重点)--Resource, Component 重要!!!
beans.xml: <?xml version="1.0" encoding="UTF-8"?> <beans xmlns="ht ...
- iOS之SDWebImage清理缓存
.找到 SDWebImage找到SDImageCache类 添加如下方法 - (float)checkTmpSize { float totalSize = 0; NSDirectoryEnumera ...
- 像51一样操作STM32的IO(转)
源:像51一样操作STM32的IO //-------------------------------------------------------------------------------- ...
- c++中vector使用
不多说,先看代码: #include <IOSTREAM> #include <VECTOR> using namespace std; int main() { cout&l ...
- mongodb学习(四)CRUD操作
CRUD操作: 1. 插入操作: 直接使用 insert可执行单个操作,也可以执行批量操作 书上的batchInsert会报错.似乎被废弃了. db.foo.insert({"bar&quo ...
- Lambda 可以转换成委托或expression树
1.关于C# Lambda Expressions: 一个Lambda Expression (译为Lambda式) 就是一个包含若干表达式和语句的匿名函数.可以被用作创建委托对象或表达式树类型.所 ...