iOS 多线程之 NSThread的基本使用
一个NSThread对象就代表一条线程 下面是NSThread开启线程的方法
- (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event {
[self openThreadWithNSThread];
[NSThread mainThread];//获取主线程
[NSThread currentThread]; //获取当前线程
}
- (void) openThreadWithNSThread {
/*
*第一个参数 目标对象 self
*第二个参数 方法选择器 调用的方法
*第三个参数 前面调用方法需要传递的参数 可以为nil
*/
//第一种方式
NSThread *thread = [[NSThread alloc] initWithTarget:self selector:@selector(threadAction:) object:@"ABC"];
thread.name = @"线程1";
//0.0-1.0之间 1.0最高 0.0最低 默认0.5 越高线程被调用的频率越大
thread.threadPriority = 1.0;
[thread start];//需要手动调用启动线程
//第二种方式
[NSThread detachNewThreadSelector:@selector(threadAction:) toTarget:self withObject:@"abc2"];//自动启动线程
//第三种方式
[self performSelectorInBackground:@selector(threadAction:) withObject:@"开启一条后台线程"];//开启一条后台线程
//block方式
NSThread *thread1 = [[NSThread alloc] initWithBlock:^{
NSLog(@"%@",[NSThread currentThread]);
}];
thread1.name = @"线程2";
thread1.threadPriority = 0.5;
[thread start];
//或者
[NSThread detachNewThreadWithBlock:^{
NSLog(@"%@",[NSThread currentThread]);
}];
}
- (void) threadAction:(NSString *)params {
NSLog(@"%@ and %@",params,[NSThread currentThread].name);
}
NSThread 创建线程的生命周期
当线程中的任务执行完毕后 线程被释放掉 可以继承NSThread创建一个新类 重写dealloc方法来验证
线程的状态

当线程处于就绪状态时线程会被移到可调度线程池里面(CPU只调度此线程池里面的线程),当处于阻塞状态时,线程会被移出可调度线程池,当处于死亡状态时 先移出线程池,再从内存中释放。
- (void)threadStatus {
//创建线程 在内存中创建一个线程 (新建状态)
NSThread *thread = [[NSThread alloc] initWithTarget:self selector:@selector(threadAction1) object:nil];
[thread start]; //就绪状态 会被放倒可调度线程池里面 只有在可调度线程池里面的线程才是可以被CPU调度的
}
//一旦线程死亡了 就不能再次开启任务
- (void)threadAction1 {
//运行状态
for (NSInteger i = ; i < ; i ++) {
if (i == ) {
//[NSThread sleepUntilDate:[NSDate dateWithTimeIntervalSinceNow:2.0]];
[NSThread sleepForTimeInterval:2.0];//阻塞状态 移出线程池
//两秒钟过后 再次进入就绪状态 等待调度进入运行状态
}
if (i == ) {
//break;//任务完成 自然死亡
[NSThread exit]; //废除线程强制进入死亡状态
}
NSLog(@"%@",[NSThread currentThread]);
}
//执行完方法之后死亡状态
}
线程的安全 也非常重要 这里介绍一种方法 后面会着重介绍
多线程的安全隐患
资源共享
1块资源可能会被多个线程共享,也就是多个线程可能会访问同一块资源 比如多个线程访问同一个对象 同一个变量 同一个文件 此时就很容易引发数据错乱和数据安全问题.

安全隐患原因分析

安全隐患的解决

问题代码
#import "ViewController.h" @interface ViewController () @property (nonatomic,strong) NSThread *threadA;//售票员A
@property (nonatomic,strong) NSThread *threadB;//售票员B
@property (nonatomic,strong) NSThread *threadC;//售票员C
@property (nonatomic,assign) NSInteger totalCount; @end @implementation ViewController - (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event {
//设置总票数
self.totalCount = ;
self.threadA = [[NSThread alloc] initWithTarget:self selector:@selector(saleTicket) object:nil];
self.threadA.name = @"售票员A";
[self.threadA start];
self.threadB = [[NSThread alloc] initWithTarget:self selector:@selector(saleTicket) object:nil];
self.threadB.name = @"售票员B";
[self.threadB start];
self.threadC = [[NSThread alloc] initWithTarget:self selector:@selector(saleTicket) object:nil];
self.threadC.name = @"售票员C";
[self.threadC start];
} //售票
- (void)saleTicket {
while () {
NSInteger count = self.totalCount;
if (count > ) {
for (NSInteger i = ; i < ; i ++) { }
//卖出去一张票
self.totalCount = count - ;
NSLog(@"%@ 卖出去一张票 还剩%zd张票",[NSThread currentThread].name,self.totalCount);
}else {
NSLog(@"票卖完了");
break;
}
} }
打印结果
-- ::38.600491+ NSThreadDemo[:] 售票员A 卖出去一张票 还剩999张票
-- ::38.600493+ NSThreadDemo[:] 售票员B 卖出去一张票 还剩999张票
-- ::38.600519+ NSThreadDemo[:] 售票员C 卖出去一张票 还剩999张票
问题解决代码
#import "ViewController.h" @interface ViewController () @property (nonatomic,strong) NSThread *threadA;//售票员A
@property (nonatomic,strong) NSThread *threadB;//售票员B
@property (nonatomic,strong) NSThread *threadC;//售票员C
@property (nonatomic,assign) NSInteger totalCount; @end @implementation ViewController - (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event {
//设置总票数
self.totalCount = ;
self.threadA = [[NSThread alloc] initWithTarget:self selector:@selector(saleTicket) object:nil];
self.threadA.name = @"售票员A";
[self.threadA start];
self.threadB = [[NSThread alloc] initWithTarget:self selector:@selector(saleTicket) object:nil];
self.threadB.name = @"售票员B";
[self.threadB start];
self.threadC = [[NSThread alloc] initWithTarget:self selector:@selector(saleTicket) object:nil];
self.threadC.name = @"售票员C";
[self.threadC start];
} //售票
- (void)saleTicket {
while () {
//锁必须是全局唯一的
@synchronized(self) {
NSInteger count = self.totalCount;
if (count > ) {
for (NSInteger i = ; i < ; i ++) { }
//卖出去一张票
self.totalCount = count - ;
NSLog(@"%@ 卖出去一张票 还剩%zd张票",[NSThread currentThread].name,self.totalCount);
}else {
NSLog(@"票卖完了");
break;
}
}
} }
互斥锁的优缺点
优点:能有效防止因多线程抢夺资源造成的数据安全问题
缺点:需要消耗大量的CPU资源
互斥锁的使用前提:多条线程抢夺同一块资源
相关专业术语:线程同步,多条线程按顺序地执行任务
互斥锁,就是使用了线程同步技术
原子和非原子属性
OC在定义属性时有nonatomic和atomic两种选择
atomic:原子属性,为setter方法加锁(默认就是atomic)
nonatomic:非原子属性,不会为setter方法加锁
@property (assign, atomic) int age; - (void)setAge:(int)age
{ @synchronized(self) {
_age = age;
}
}
原子和非原子属性的选择
nonatomic和atomic对比
atomic:线程安全,需要消耗大量的资源(并非是真正的线程安全 更准确的说应该是读写安全,但并不是线程安全的,因为别的线程还能进行读写之外的其他操作。线程安全需要开发者自己来保证。)
nonatomic:非线程安全,适合内存小的移动设备
iOS开发的建议
所有属性都声明为nonatomic
尽量避免多线程抢夺同一块资源
尽量将加锁、资源抢夺的业务逻辑交给服务器端处理,减小移动客户端的压力
iOS 多线程之 NSThread的基本使用的更多相关文章
- iOS 多线程(NSThread、GCD、NSOperation)
ios中得多线程技术主要使用3种:NSThread.NSOperation和GCD 一.NSThread: 最轻量级方法,但是不安全需要手动加锁,需要自己管理生命周期 NSThread的使用方法有2种 ...
- iOS多线程开发--NSThread NSOperation GCD
多线程 当用户播放音频.下载资源.进行图像处理时往往希望做这些事情的时候其他操作不会被中 断或者希望这些操作过程中更加顺畅.在单线程中一个线程只能做一件事情,一件事情处理不完另一件事就不能开始,这样势 ...
- IOS多线程(NSThread)
1.创建方法 使用NSThread创建线程主要有两个个方法,分别如下 NSThread* myThread = [[NSThread alloc] initWithTarget:self sele ...
- iOS GCD NSOperation NSThread等多线程各种举例详解(拷贝)
2年多的iOS之路匆匆而过,期间也拜读来不少大神的博客,近来突然为自己一直做伸手党感到羞耻,是时候回馈社会.回想当年自己还是小白的时候,照着一些iOS多线程教程学,也只是照抄,只知其然.不知其所以然. ...
- iOS多线程编程之NSThread的使用
目录(?)[-] 简介 iOS有三种多线程编程的技术分别是 三种方式的有缺点介绍 NSThread的使用 NSThread 有两种直接创建方式 参数的意义 PS不显式创建线程的方法 下载图片的例子 ...
- iOS多线程编程之NSThread的使用(转)
本文由http://blog.csdn.net/totogo2010/原创 1.简介: 1.1 iOS有三种多线程编程的技术,分别是: 1..NSThread 2.Cocoa NSOperation ...
- iOS 多线程学习笔记 —— NSThread
本文复制.参考自文章:iOS多线程编程之NSThread的使用 ,主要为了加强个人对知识的理解和记忆,不做他用.原作者声明: 著作权声明:本文由http://blog.csdn.net/totogo ...
- [转]iOS多线程编程之NSThread的使用
1.简介: 1.1 iOS有三种多线程编程的技术,分别是: 1..NSThread 2.Cocoa NSOperation (iOS多线程编程之NSOperation和NSOperationQueue ...
- iOS 多线程 简单学习NSThread NSOperation GCD
1:首先简单介绍什么叫线程 可并发执行的,拥有最小系统资源,共享进程资源的基本调度单位. 共用堆,自有栈(官方资料说明iOS主线程栈大小为1M,其它线程为512K). 并发执行进度不可控,对非原子操作 ...
随机推荐
- .Net基础——程序集与CIL HttpClient封装方法 .Net Core 编码规范 C#中invoke和beginInvoke的使用 WebServeice 动态代理类
.Net基础——程序集与CIL 1. 程序集和CIL: 程序集是由.NET语言的编译器接受源代码文件产生的输出文件,通常分为 exe和dll两类,其中exe包含Main入口方法可以双击执行,dll ...
- 我也来谈谈使用Zen Coding快速开发html和css原理
zen coding 是一种仿css选择器的语法来快速开发html和css的开源项目.现已更名为Emmet.可以到github上下载拜读.在这个都想偷懒的世界里,此方法可以极大的缩短开发人员的开发时间 ...
- 有关IM即时通讯原理
在网上搜索了一些资料,谈谈自己对IM即时通讯的理解 IM全称为Instant Messaging,即时通讯,如qq那种的. 现在有两个用户UserA, UserB, 俩人是一个IM通讯软件的好友,Us ...
- unity, windows: Unhandled Exception: System.UnauthorizedAccessException: Access to the path "XXX\Temp\Assembly-CSharp.dll.mdb" is denied
的windows上使用unity,修改过脚本或inspector中的数值后运行编辑器报错: Unhandled Exception: System.UnauthorizedAccessExceptio ...
- ARM处理器的运行模式
ARM处理器的7种运行模式 用户模式( usr ):ARM处理器正常的程序执行状态: 快速中断模式( fiq ):用于高速数据传输或通道处理: 外部中断模式( irq):用于通常的中断处理: 管理模式 ...
- [置顶] Android开发笔记(成长轨迹)
分类: 开发学习笔记2013-06-21 09:44 26043人阅读 评论(5) 收藏 Android开发笔记 1.控制台输出:called unimplemented OpenGL ES API ...
- AutoLayout详解+手把手实战(转载)
首先说一下这篇博客虽然是标记为原创,但是事实并非本人亲自写出来的,知识点和例子本人花了一天各处查 找和整理最终决定写一个汇总的详解,解去各位朋友到处盲目查找的必要,因为不是转载某一个人的内容,故此不标 ...
- DataUml Design 介绍9 - DataUML 1.3版本功能(查询分析器功能等)
DataUML 1.3 (下载)主要更新内容如下: 1.增加查询分析器功能: 2.增加打开历史文件记录功能: 3.修改查询对象功能: 4.增加显示对象长度功能: 5.增加配置显示表字段功能: 6.增加 ...
- Unity3D 移动开发代码优化
1. 尽量避免每帧处理 比方: function Update() { DoSomeThing(); } 可改为每5帧处理一次: function Update() { if(Time.frameCo ...
- 一步一步解析H.264码流的NALU(SPS,PSS,IDR)获取宽高和帧率
分析H.264码流的工具 CodecVisa,StreamEye以及VM Analyzer NALU是由NALU头和RBSP数据组成,而RBSP可能是SPS,PPS,Slice或SEI 而且SPS位于 ...