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). 并发执行进度不可控,对非原子操作 ...
随机推荐
- C++ 和 java 使用 AES CBC 128 加解密
Java 使用jce, code: import javax.crypto.Cipher; import javax.crypto.spec.IvParameterSpec; import javax ...
- CSAPP:异常控制流
在一般的情况下,处理器处理的指令序列是相邻的(顺序执行). 异常控制流提供了指令的跳转,它一部分是由硬件实现的,一部分是由操作系统实现的. 异常处理 在系统启动时,操作系统分配和初始化一张称为异常表的 ...
- 1高并发server:多路IO之select
1 select A:select能监听的文件描写叙述符个数受限于FD_SETSIZE,一般为1024.单纯改变进程打开 的文件描写叙述符个数并不能改变select监听文件个数 B:解决1024 ...
- 【方法1】删除Map中Value反复的记录,而且仅仅保留Key最小的那条记录
介绍 晚上无聊的时候,我做了一个測试题,測试题的大体意思是:删除Map中Value反复的记录,而且仅仅保留Key最小的那条记录. 比如: I have a map with duplicate val ...
- ace admin 下拉选择Multiple-select组件
一.组件说明以及API 1.第一个组件是写bootstrap table的主人公 wenzhixin 封装的一个组件—— multiple-select.这个组件风格简单.文档全.功能强大.但是觉得它 ...
- 10710 - Chinese Shuffle(数论+完美洗牌)
UVA 10710 - Chinese Shuffle 题目链接 题意:给定n张牌,完美洗牌n - 1次,问是否会变回原来的序列 思路:完美洗牌: 如果有a1a2a3...anb1b2b3...bn的 ...
- MapReduce-MulitipleOutputs实现自己定义输出到多个文件夹
输入源数据例子: Source1-0001 Source2-0002 Source1-0003 Source2-0004 Source1-0005 Source2-0006 Source3-0007 ...
- 分布式服务框架 Zookeeper(四)官方编程指南
握草,是不是加了官方两个字就可以唬人了. 使用ZooKeeper开发分布式应用 简介 这篇文档是为了那些想利用ZooKeeper的协调服务来构建分布式应用的开发人员而写滴,不相干的走一边去哈.在这儿有 ...
- Irrelevant Elements UVA - 1635 二项式定理+组合数公式+素数筛+唯一分解定理
/** 题目:Irrelevant Elements UVA - 1635 链接:https://vjudge.net/problem/UVA-1635 题意:給定n,m;題意抽象成(a+b)^(n- ...
- 深入理解yum工作原理
前言 在前面一篇rpm包制作描述了rpm的打包过程,这篇文章主要讲述yum的工作原理. yum 运行原理 yum的工作需要两部分来合作,一部分是yum服务器,还有就是client的yum工具.下面分别 ...