文档章节

iOS开发 多线程(二) NSThread的使用(转)

神补刀
 神补刀
发布于 2015/08/18 11:24
字数 1350
阅读 655
收藏 0

每个iOS应用程序都有个专门用来更新显示UI界面、处理用户的触摸事件的主线程,因此不能将其他太耗时的操作放在主线程中执行,不然会造成主线程堵塞(出现卡机现象),带来极坏的用户体验。一般的解决方案就是将那些耗时的操作放到另外一个线程中去执行,多线程编程是防止主线程堵塞,增加运行效率的最佳方法

iOS支持多个层次的多线程编程,层次越高的抽象程度越高,使用也越方便,也是苹果最推荐使用的方法。下面根据抽象层次从低到高依次列出iOS所支持的多线程编程方法:

1.Thread :是三种方法里面相对轻量级的,但需要管理线程的生命周期、同步、加锁问题,这会导致一定的性能开销
2.Cocoa Operations:是基于OC实现的,NSOperation以面向对象的方式封装了需要执行的操作,不必关心线程管理、同步等问题。NSOperation是一个抽象基类,iOS提供了两种默认实现:NSInvocationOperation和NSBlockOperation,当然也可以自定义NSOperation
3.Grand Central Dispatch(简称GCD,iOS4才开始支持):提供了一些新特性、运行库来支持多核并行编程,它的关注点更高:如何在多个cpu上提升效率


这篇文章简单介绍了第一种多线程编程的方式,主要是利用NSThread这个类,一个NSThread实例代表着一条线程

一、NSthread的初始化

1.动态方法

[java] view plaincopy

  1. - (id)initWithTarget:(id)target selector:(SEL)selector object:(id)argument;  

[java] view plaincopy

  1. // 初始化线程  

  2. NSThread *thread = [[NSThread alloc] initWithTarget:self selector:@selector(run) object:nil];  

  3. // 设置线程的优先级(0.0 - 1.0,1.0最高级)  

  4. thread.threadPriority = 1;  

  5. // 开启线程  

  6. [thread start];  

参数解析:

selector :线程执行的方法,这个selector最多只能接收一个参数
target :selector消息发送的对象
argument : 传给selector的唯一参数,也可以是nil


2.静态方法

[java] view plaincopy

  1. + (void)detachNewThreadSelector:(SEL)selector toTarget:(id)target withObject:(id)argument;  

[java] view plaincopy

  1. [NSThread detachNewThreadSelector:@selector(run) toTarget:self withObject:nil];  

  2. // 调用完毕后,会马上创建并开启新线程  


3.隐式创建线程的方法

[java] view plaincopy

  1. [self performSelectorInBackground:@selector(run) withObject:nil];  


二、获取当前线程

[java] view plaincopy

  1. NSThread *current = [NSThread currentThread];  


三、获取主线程

[java] view plaincopy

  1. NSThread *main = [NSThread mainThread];  


四、暂停当前线程

[java] view plaincopy

  1. // 暂停2s  

  2. [NSThread sleepForTimeInterval:2];  

  3.   

  4. // 或者  

  5. NSDate *date = [NSDate dateWithTimeInterval:2 sinceDate:[NSDate date]];  

  6. [NSThread sleepUntilDate:date];  


五、线程间的通信

1.在指定线程上执行操作

[java] view plaincopy

  1. [self performSelector:@selector(run) onThread:thread withObject:nil waitUntilDone:YES];  


2.在主线程上执行操作

[java] view plaincopy

  1. [self performSelectorOnMainThread:@selector(run) withObject:nil waitUntilDone:YES];  


3.在当前线程执行操作

[java] view plaincopy

  1. [self performSelector:@selector(run) withObject:nil];  


六、优缺点

1.优点:NSThread比其他两种多线程方案较轻量级,更直观地控制线程对象

2.缺点:需要自己管理线程的生命周期,线程同步。线程同步对数据的加锁会有一定的系统开销

--------------------------------------------

--------------另外一个博客的补充----------

2.3 线程同步

我们演示一个经典的卖票的例子来讲NSThread的线程同步:

.h

[cpp] view plaincopy

  1. #import <UIKit/UIKit.h>  

  2.   

  3. @class ViewController;  

  4.   

  5. @interface AppDelegate : UIResponder <UIApplicationDelegate>  

  6. {  

  7.     int tickets;  

  8.     int count;  

  9.     NSThread* ticketsThreadone;  

  10.     NSThread* ticketsThreadtwo;  

  11.     NSCondition* ticketsCondition;  

  12.     NSLock *theLock;  

  13. }  

  14. @property (strong, nonatomic) UIWindow *window;  

  15.   

  16. @property (strong, nonatomic) ViewController *viewController;  

  17.   

  18. @end  

[cpp] view plaincopy

  1. - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions  

  2. {  

  3.       

  4.     tickets = 100;  

  5.     count = 0;  

  6.     theLock = [[NSLock alloc] init];  

  7.     // 锁对象  

  8.     ticketsCondition = [[NSCondition alloc] init];  

  9.     ticketsThreadone = [[NSThread alloc] initWithTarget:self selector:@selector(run) object:nil];  

  10.     [ticketsThreadone setName:@"Thread-1"];  

  11.     [ticketsThreadone start];  

  12.       

  13.       

  14.     ticketsThreadtwo = [[NSThread alloc] initWithTarget:self selector:@selector(run) object:nil];  

  15.     [ticketsThreadtwo setName:@"Thread-2"];  

  16.     [ticketsThreadtwo start];  

  17.       

  18.     self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];  

  19.     // Override point for customization after application launch.  

  20.     self.viewController = [[ViewController alloc] initWithNibName:@"ViewController" bundle:nil];  

  21.     self.window.rootViewController = self.viewController;  

  22.     [self.window makeKeyAndVisible];  

  23.     return YES;  

  24. }  

  25.   

  26. - (void)run{  

  27.     while (TRUE) {  

  28.         // 上锁  

  29. //        [ticketsCondition lock];  

  30.         [theLock lock];  

  31.         if(tickets >= 0){  

  32.             [NSThread sleepForTimeInterval:0.09];  

  33.             count = 100 - tickets;  

  34.             NSLog(@"当前票数是:%d,售出:%d,线程名:%@",tickets,count,[[NSThread currentThread] name]);  

  35.             tickets--;  

  36.         }else{  

  37.             break;  

  38.         }  

  39.         [theLock unlock];  

  40. //        [ticketsCondition unlock];  

  41.     }  

  42. }  

如果没有线程同步的lock,卖票数可能是-1.加上lock之后线程同步保证了数据的正确性。
上面例子我使用了两种锁,一种NSCondition ,一种是:NSLock。 NSCondition我已经注释了。

线程的顺序执行

他们都可以通过

        [ticketsCondition signal]; 发送信号的方式,在一个线程唤醒另外一个线程的等待。

比如:

[cpp] view plaincopy

  1. #import "AppDelegate.h"  

  2.   

  3. #import "ViewController.h"  

  4.   

  5. @implementation AppDelegate  

  6.   

  7. - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions  

  8. {  

  9.       

  10.     tickets = 100;  

  11.     count = 0;  

  12.     theLock = [[NSLock alloc] init];  

  13.     // 锁对象  

  14.     ticketsCondition = [[NSCondition alloc] init];  

  15.     ticketsThreadone = [[NSThread alloc] initWithTarget:self selector:@selector(run) object:nil];  

  16.     [ticketsThreadone setName:@"Thread-1"];  

  17.     [ticketsThreadone start];  

  18.       

  19.     ticketsThreadtwo = [[NSThread alloc] initWithTarget:self selector:@selector(run) object:nil];  

  20.     [ticketsThreadtwo setName:@"Thread-2"];  

  21.     [ticketsThreadtwo start];  

  22.       

  23.     NSThread *ticketsThreadthree = [[NSThread alloc] initWithTarget:self selector:@selector(run3) object:nil];  

  24.     [ticketsThreadthree setName:@"Thread-3"];  

  25.     [ticketsThreadthree start];      

  26.     self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];  

  27.     // Override point for customization after application launch.  

  28.     self.viewController = [[ViewController alloc] initWithNibName:@"ViewController" bundle:nil];  

  29.     self.window.rootViewController = self.viewController;  

  30.     [self.window makeKeyAndVisible];  

  31.     return YES;  

  32. }  

  33.   

  34. -(void)run3{  

  35.     while (YES) {  

  36.         [ticketsCondition lock];  

  37.         [NSThread sleepForTimeInterval:3];  

  38.         [ticketsCondition signal];  

  39.         [ticketsCondition unlock];  

  40.     }  

  41. }  

  42.   

  43. - (void)run{  

  44.     while (TRUE) {  

  45.         // 上锁  

  46.         [ticketsCondition lock];  

  47.         [ticketsCondition wait];  

  48.         [theLock lock];  

  49.         if(tickets >= 0){  

  50.             [NSThread sleepForTimeInterval:0.09];  

  51.             count = 100 - tickets;  

  52.             NSLog(@"当前票数是:%d,售出:%d,线程名:%@",tickets,count,[[NSThread currentThread] name]);  

  53.             tickets--;  

  54.         }else{  

  55.             break;  

  56.         }  

  57.         [theLock unlock];  

  58.         [ticketsCondition unlock];  

  59.     }  

  60. }  

wait是等待,我加了一个 线程3 去唤醒其他两个线程锁中的wait

其他同步

我们可以使用指令 @synchronized 来简化 NSLock的使用,这样我们就不必显示编写创建NSLock,加锁并解锁相关代码。
- (void)doSomeThing:(id)anObj
{
    @synchronized(anObj)
    {
        // Everything between the braces is protected by the @synchronized directive.
    }
}


本文转载自:http://blog.csdn.net/q199109106q/article/details/8565844

神补刀
粉丝 19
博文 78
码字总数 38937
作品 0
广州
程序员
私信 提问
iOS多线程编程之一——NSThread线程管理

iOS多线程编程之一——NSThread线程管理 NSTread是iOS中进行多线程开发的一个类,其结构逻辑清晰,使用十分方便,但其封装度和性能不高,线程周期,加锁等需要手动处理。 一、NSThread类方法...

珲少
2015/05/19
0
2
关于iOS多线程,这边勉强可以看看(OC&Swift)

iOS开发多线程总是绕不过的坎,看了很多前辈们优秀的文章,如:关于iOS多线程,我说,你听,没准你就懂了!、谈iOS多线程(NSThread、NSOperation、GCD)编程、iOS多线程:『GCD』详尽总结、i...

Andy_Ron
2018/08/26
0
0
iOS按钮倒计时在进入后台不继续计时的处理

iOS程序进入后台后十分钟之内就会被系统kill掉,我想要程序进入后台后仍然运行计时功能,怎么解决呢? 方法一:可以使用记录开始时间和获取当前时间的时间差进行处理 还是直接上代码: 下面的...

云上飞飞
2018/07/06
0
0
iOS多线程编程之NSThread的使用

iOS多线程编程之NSThread的使用 1、简介: 1.1 iOS有三种多线程编程的技术,分别是: 1.、NSThread 2、Cocoa NSOperation (iOS多线程编程之NSOperation和NSOperationQueue的使用) 3、GCD 全...

malawo
2013/09/05
0
0
iOS开发系列--并行开发其实很容易

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/jianxin160/article/details/47753225 --多线程开发 概览 大家都知道,在开发过程中应该尽可能减少用户等待时...

KenshinCui
2015/08/18
0
0

没有更多内容

加载失败,请刷新页面

加载更多

OSChina 周四乱弹 —— 如果人生有机会 carl+z

Osc乱弹歌单(2019)请戳(这里) 【今日歌曲】 @巴拉迪维 :How I wish I could choose between Heaven and Hell. How I wish I would save my soul. #今日歌曲推荐# 《Tears And Rain》- J...

小小编辑
46分钟前
171
6
一步步教你怎么用python写贪吃蛇游戏

目录 0 引言 1 环境 2 需求分析 3 代码实现 4 后记 0 引言 前几天,星球有人提到贪吃蛇,一下子就勾起了我的兴趣,毕竟在那个Nokia称霸的年代,这款游戏可是经典中的经典啊!而用Python(蛇)...

上海小胖
今天
1
0
NIO基于长度域的报文在Netty下的解码

1, 先复习一下粘包/拆包 1.1, 粘包/拆包的含义 TCP是个“流”协议, 并不了解上层业务数据的具体含义, 它会根据TCP缓冲区的实际情况进行包的划分,所以在业务上认为,一个完整的包可能会被TCP...

老菜鸟0217
今天
8
0
从零开始搭建spring-cloud(2) ----ribbon

在微服务架构中,业务都会被拆分成一个独立的服务,服务与服务的通讯是基于http restful的。Spring cloud有两种服务调用方式,一种是ribbon+restTemplate,另一种是feign。 其实我们已经在上...

Vincent-Duan
今天
28
0
get和post的区别?

doGet:路径传参。效率高,安全性差(get的传送数据量有限制,不能大于2Kb) doPOST:实体传参。效率低,安全性好 建议: 1、get方式的安全性较Post方式要差些,包含机密信息的话,建议用Pos...

花无谢
昨天
4
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部