ios学习路线—iOS高级(NSThread)

简介
NSThread是轻量级的,但也是使用起来最负责的,你需要自己管理thread的生命周期,线程之间的同步。线程共享同一个应用程序的部分内存空间,它们拥有对数据相同的访问权限。
你得协调多个线程 对同一数据的访问,一般做法是在访问之前加锁,这会导致一定的性能开销。在 iOS 中我们可以使用多种形式的 thread。

NSThread的使用
NSThread有两种直接创建方式

//实例方法-会直接创建线程并且开始运行线程
[NSThread detachNewThreadSelector:@selector(doSomething:) toTarget:self withObject:nil];

//类方法-先创建线程对象,然后再运行线程操作,在运行线程操作前可以设置线程的优先级等线程信息
NSThread* myThread = [[NSThread alloc] initWithTarget:self  
                                        selector:@selector(doSomething:)  
                                        object:nil];  
[myThread start];
- 

参数的意义
selector :线程执行的方法,这个selector只能有一个参数,而且不能有返回值。
target :selector消息发送的对象。
argument:传输给target的唯一参数,也可以是nil。

不显式创建线程的方法

//创建一个线程在子线程执行,aSelector代表了新创建的线程,arg是传入的参数
- (void)performSelectorInBackground:(SEL)aSelector withObject:(id)arg
//该方法的作用是在主线程中,执行制定的方法(代码块)
//waitUntilDone:YES指定,当前线程是否要被阻塞,直到主线程将我们制定的代码块执行完。
- (void)performSelectorOnMainThread:(SEL)aSelector withObject:(id)arg waitUntilDone:(BOOL)wait; 

下载图片的例子

@interface ViewController ()  

@end

@implementation ViewController

- (void)viewDidLoad  
{  
    [super viewDidLoad];  

    //[NSThread detachNewThreadSelector:@selector(downloadImage:) toTarget:self withObject:kURL];  
    NSThread *thread = [[NSThread alloc]initWithTarget:self selector:@selector(downloadImage:) object:kURL];  
    [thread start];  
}  

- (void)didReceiveMemoryWarning  
{  
    [super didReceiveMemoryWarning];  
    // Dispose of any resources that can be recreated.  
}  

-(void)downloadImage:(NSString *) url{  
    NSData *data = [[NSData alloc] initWithContentsOfURL:[NSURL URLWithString:url]];  
    UIImage *image = [[UIImage alloc]initWithData:data];  
    if(image == nil){  

    }else{  
        [self performSelectorOnMainThread:@selector(updateUI:) withObject:image waitUntilDone:YES];  
    }  
}  

-(void)updateUI:(UIImage*) image{  
    self.imageView.image = image;  
} 

@end

线程间通信
线程下载完成图片后怎么通知主线程更新界面呢?
[self performSelectorOnMainThread:@selector(updateUI:) withObject:image waitUntilDone:YES];
performSelectorOnMainThread是NSObject的方法,除了可以更新主线程的数据外,还可以更新其他线程的比如:
用:performSelector:onThread:withObject:waitUntilDone:

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

@class ViewController;  

@interface AppDelegate : UIResponder <UIApplicationDelegate>  
{  
    int tickets;  
    int count;  
    NSThread* ticketsThreadone;  
    NSThread* ticketsThreadtwo;  
    NSCondition* ticketsCondition;  
    NSLock *theLock;  
}  
@property (strong, nonatomic) UIWindow *window;  

@property (strong, nonatomic) ViewController *viewController;  

@end 
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions  
{  

    tickets = 100;  
    count = 0;  
    theLock = [[NSLock alloc] init];  
    // 锁对象  
    ticketsCondition = [[NSCondition alloc] init];  
    ticketsThreadone = [[NSThread alloc] initWithTarget:self selector:@selector(run) object:nil];  
    [ticketsThreadone setName:@"Thread-1"];  
    [ticketsThreadone start];  


    ticketsThreadtwo = [[NSThread alloc] initWithTarget:self selector:@selector(run) object:nil];  
    [ticketsThreadtwo setName:@"Thread-2"];  
    [ticketsThreadtwo start];  

    self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];  
    // Override point for customization after application launch.  
    self.viewController = [[ViewController alloc] initWithNibName:@"ViewController" bundle:nil];  
    self.window.rootViewController = self.viewController;  
    [self.window makeKeyAndVisible];  
    return YES;  
}  

- (void)run{  
    while (TRUE) {  
        // 上锁  
//        [ticketsCondition lock];  
        [theLock lock];  
        if(tickets >= 0){  
            [NSThread sleepForTimeInterval:0.09];  
            count = 100 - tickets;  
            NSLog(@"当前票数是:%d,售出:%d,线程名:%@",tickets,count,[[NSThread currentThread] name]);  
            tickets--;  
        }else{  
            break;  
        }  
        [theLock unlock];  
//        [ticketsCondition unlock];  
    }  
}  

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

线程的顺序执行
他们都可以通过[ticketsCondition signal]; 发送信号的方式,在一个线程唤醒另外一个线程的等待。

@implementation AppDelegate  

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions  
{  

    tickets = 100;  
    count = 0;  
    theLock = [[NSLock alloc] init];  
    // 锁对象  
    ticketsCondition = [[NSCondition alloc] init];  
    ticketsThreadone = [[NSThread alloc] initWithTarget:self selector:@selector(run) object:nil];  
    [ticketsThreadone setName:@"Thread-1"];  
    [ticketsThreadone start];  

    ticketsThreadtwo = [[NSThread alloc] initWithTarget:self selector:@selector(run) object:nil];  
    [ticketsThreadtwo setName:@"Thread-2"];  
    [ticketsThreadtwo start];  

    NSThread *ticketsThreadthree = [[NSThread alloc] initWithTarget:self selector:@selector(run3) object:nil];  
    [ticketsThreadthree setName:@"Thread-3"];  
    [ticketsThreadthree start];      
    self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];  
    // Override point for customization after application launch.  
    self.viewController = [[ViewController alloc] initWithNibName:@"ViewController" bundle:nil];  
    self.window.rootViewController = self.viewController;  
    [self.window makeKeyAndVisible];  
    return YES;  
}  

-(void)run3{  
    while (YES) {  
        [ticketsCondition lock];  
        [NSThread sleepForTimeInterval:3];  
        [ticketsCondition signal];  
        [ticketsCondition unlock];  
    }  
}  

- (void)run{  
    while (TRUE) {  
        // 上锁  
        [ticketsCondition lock];  
        [ticketsCondition wait];  
        [theLock lock];  
        if(tickets >= 0){  
            [NSThread sleepForTimeInterval:0.09];  
            count = 100 - tickets;  
            NSLog(@"当前票数是:%d,售出:%d,线程名:%@",tickets,count,[[NSThread currentThread] name]);  
            tickets--;  
        }else{  
            break;  
        }  
        [theLock unlock];  
        [ticketsCondition unlock];  
    }  
}  

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

其他同步
我们可以使用指令 @synchronized 来简化 NSLock的使用,这样我们就不必显示编写创建NSLock,加锁并解锁相关代码。
- (void)doSomeThing:(id)anObj
{
@synchronized(anObj)
{
// Everything between the braces is protected by the @synchronized directive.
}
}
还有其他的一些锁对象,比如:循环锁NSRecursiveLock,条件锁NSConditionLock,分布式锁NSDistributedLock等等,可以自己看官方文档学习

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值