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

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

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

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


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

1、NSthread的初始化ide

1.动态方法性能

[java] view plaincopyatom

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

[java] view plaincopy.net

  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];  


2、获取当前线程

[java] view plaincopy

  1. NSThread *current = [NSThread currentThread];  


3、获取主线程

[java] view plaincopy

  1. NSThread *main = [NSThread mainThread];  


4、暂停当前线程

[java] view plaincopy

  1. // 暂停2s  

  2. [NSThread sleepForTimeInterval:2];  

  3.   

  4. // 或者  

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

  6. [NSThread sleepUntilDate:date];  


5、线程间的通讯

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];  


6、优缺点

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.    }}

相关文章
相关标签/搜索