NSThread 创建
一个 NSThread 对象就代表一条线程 需要手动管理线程的生命周期, 处理线程同步等问题
- // 下面方法处于主线程
- - (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event {
- #pragma mark - 方法一
- // 创建一个 NSThread
- NSThread * thread = [[NSThread alloc]initWithTarget:self selector:@selector(threadRunOne:) object:@"Thread"];
- // 线程一启动, 就会在线程 thread 中执行 self 的 threadRun 方法
- [thread start];
- #pragma mark - 方法二
- // 分离创建一个 NSThread 此方法立刻执行
- [NSThread detachNewThreadSelector:@selector(threadRunTwo:) toTarget:self withObject:@"Detach"];
- #pragma mark - 方法三
- //performSelectorInBackground 就是在后台 (子线程) 运行! 是 NSObject 的分类 意味着所有的基于 NSObject 的都可以使用这个方法 很方便 不用 NSThread 对象
- [self performSelectorInBackground:@selector(threadRunThree:) withObject:@"background"];
- }
- // 以下都在子线程
- -(void)threadRunOne:(id)obj{
- for (int i = 0; i < 5; i++) {
- NSLog(@"Thread=%@",[NSThread currentThread]);
- }
- }
NSThread 属性
- // 启动线程 进入就绪状态 -> 运行状态当线程任务执行完毕, 自动进入死亡状态
- - (void)start;
- // 线程取消
- - (void)cancel;
- // 主线程
- - (void)main;
- // 阻塞 (暂停) 线程
- + (void)sleepUntilDate:(NSDate *)date;
- // 进入阻塞状态
- + (void)sleepForTimeInterval:(NSTimeInterval)ti;
- // 强制停止线程 进入死亡状态
- // 注 : 一旦线程停止 (死亡) 了, 就不能再次开启任务
- + (void)exit;
- // 主线程使用的话会阻塞(界面无法交互), 但不会崩溃, 且无法再次开启.
- // 主线程相关用法
- + (NSThread *)mainThread; // 获得主线程
- + (BOOL)isMainThread; // 是否为主线程
- - (BOOL)isMainThread; // 是否为主线程
- // 获得当前线程
- NSThread *current = [NSThread currentThread];
- // 线程的名字
- - (void)setName:(NSString *)name;
- - (NSString *)name;
- xxx.threadPriority=0.1
- // 优先级 从 0.0 -- 1.0 默认值 0.5
- /** 优先级翻转
- 优先级 只是保证 CPU 调度的可能性会高
- 多线程目的: 将耗时操作放在后台, 不阻塞 UI 线程!
- 建议: 在开发的时候, 不要修改优先级
- */
线程的状态
新建 (alloc init) --> 就绪 (star)<==> 运行 (cpu-runing)--> 死亡(exit)
新建 -->就绪 <==> 运行 -->阻塞(sleep)
阻塞 -->死亡
线程间通信
在 1 个进程中, 线程往往不是孤立存在的, 多个线程之间需要经常进行通信
线程间通信的体现
1 个线程传递数据给另 1 个线程
在 1 个线程中执行完特定任务后, 转到另 1 个线程继续执行任务
常用的有三种:
1 指定当前线程执行操作
- [self performSelector:@selector(threadRun)];
- [self performSelector:@selector(threadRun) withObject:nil];
- [self performSelector:@selector(threadRun) withObject:nil afterDelay:2.0];
2(在其他线程中)指定主线程执行操作
注意: 更新 UI 要在主线程中进行
- [self performSelectorOnMainThread:@selector(threadRun) withObject:nil
- waitUntilDone:YES];
3(在主线程中)指定其他线程执行操作
- // 这里指定为某个线程
- [self performSelector:@selector(threadRun) onThread:newThread
- withObject:nil waitUntilDone:YES];
- //- (void)performSelectorOnMainThread:(SEL)aSelector withObject:(id)arg waitUntilDone:(BOOL)wait;
- //- (void)performSelector:(SEL)aSelector onThread:(NSThread *)thr withObject:(id)arg waitUntilDone:(BOOL)wait;
- // 这里指定为后台线程
- [self performSelectorInBackground:@selector(threadRun) withObject:nil];
线程同步
线程和其他线程可能会共享一些资源, 当多个线程同时读写同一份共享资源的时候, 可能会引起冲突线程同步是指是指在一定的时间内只允许某一个线程访问某个资源
iOS 实现线程加锁有 NSLock 和 @synchronized 两种方式
解决办法互斥锁
互斥锁使用格式
@synchronized(锁对象, 一般是 self, 全局属性) { // 需要锁定的代码 }
只用一把锁, 多锁是无效的
局部属性, 每一个线程单独拥有的, 因此没法加锁!
互斥锁的优缺点
优点: 能有效防止因多线程抢夺资源造成的数据安全问题
缺点: 需要消耗大量的 CPU 资源
互斥锁的使用前提
多条线程抢夺同一块资源
互斥锁 就是使用了线程同步技术)
资源共享
1 块资源可能会被多个线程共享, 也就是多个线程可能会访问同一块资源
当多个线程访问同一块资源时, 很容易引发数据错乱和数据安全问题
举例
在多线程开发中, 不要相信一次的运行结果!!
其它参考资料
下一节 : GCD
来源: http://www.jianshu.com/p/2e9d3c33b7e9