NSThread使用详解

来源:互联网 发布:世界征服者3mac破解版 编辑:程序博客网 时间:2024/05/16 19:59

上一节中,我转载他人的文章,对多线程的理论知识进行了大致的描述,如果想了解的话,请点击这里。接下来的几节内容,我将一一介绍各自的使用。


1. NSThread相关的主要方法:

创建、启动线程

NSThread *thread = [[NSThread alloc] initWithTarget:self selector:@selector(run) object:nil];[thread start];// 线程一启动,就会在线程thread中执行self的run方法

主线程相关方法
+ (NSThread *)mainThread; // 获得主线程
- (BOOL)isMainThread; // 是否为主线程+ (BOOL)isMainThread; // 是否为主线程

得到当前线程、获取线程名字

NSThread *current = [NSThread currentThread];- (void)setName:(NSString *)name;- (NSString *)name;


创建线程后自动启动线程

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

隐式创建并启动线程

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

2. 线程状态示意图


3. 互斥锁

@synchronized(锁对象) { // 需要锁定的代码  }

注意:锁定1份代码只用1把锁,用多把锁是无效的

互斥锁的优缺点
优点:能有效防止因多线程抢夺资源造成的数据安全问题
缺点:需要消耗大量的CPU资源

互斥锁的使用前提:多条线程抢夺同一块资源

相关专业术语:线程同步
线程同步的意思是:多条线程按顺序地执行任务
互斥锁,就是使用了线程同步技术


4. 原子性和非原子性

OC在定义属性时有nonatomic和atomic两种选择
atomic:原子属性,为setter方法加锁(默认就是atomic)
nonatomic:非原子属性,不会为setter方法加锁

atomic加锁原理
@property (assign, atomic) int age;- (void)setAge:(int)age{    @synchronized(self) {        _age = age;    }}

nonatomic和atomic对比
atomic:线程安全,需要消耗大量的资源
nonatomic:非线程安全,适合内存小的移动设备

iOS开发的建议
所有属性都声明为nonatomic
尽量避免多线程抢夺同一块资源
尽量将加锁、资源抢夺的业务逻辑交给服务器端处理,减小移动客户端的压力


5. 线程间通信

什么叫做线程间通信

在1个进程中,线程往往不是孤立存在的,多个线程之间需要经常进行通信

线程间通信的体现
1个线程传递数据给另1个线程
在1个线程中执行完特定任务后,转到另1个线程继续执行任务

线程间通信常用方法

- (void)performSelectorOnMainThread:(SEL)aSelector withObject:(id)arg waitUntilDone:(BOOL)wait;- (void)performSelector:(SEL)aSelector onThread:(NSThread *)thr withObject:(id)arg waitUntilDone:(BOOL)wait;

线程间通信示例 – 图片下载



6. Demo 演示

业务描述(卖票): 模拟两个线程抢夺一份资源

运行结果图:



主要代码说明:

1.  属性及方法定义:

/*     1. NSThread 可以使用NSLock 进行加锁工作    2. NSOperation和GCD  应该使用同步锁 :@synchronized(self),并且抢夺的内存资源应该定义为 atomic 的属性 */@property (atomic,assign) int tickets;@property (atomic,strong) NSLock *lock;//  显示结果区域@property (weak, nonatomic) IBOutlet UITextView *messageBoard;//  开始售票- (IBAction)threadSale;

2.  点击Start对应方法的代码:

- (IBAction)threadSale {    // 1. 先设定销售票的数量    _tickets = 100;        // 创建线程1    NSThread *thread1 = [[NSThread alloc]initWithTarget:self selector:@selector(threadSaleMethod) object:nil];    // 便于跟踪时知道谁在工作    thread1.name = @"售票线程-1";    // 启动线程    [thread1 start];        // 创建线程2    NSThread *thread2 = [[NSThread alloc]initWithTarget:self selector:@selector(threadSaleMethod) object:nil];    thread2.name = @"售票线程-2";    [thread2 start];}

3.  子线程执行内容对应的方法

- (void)threadSaleMethod {    // 1. 定义锁,懒加载    if (_lock == nil) {        _lock = [[NSLock alloc] init];    }        while(YES)    {        [_lock lock];        if(_tickets > 0)        {            NSString *message = [NSString stringWithFormat:@"当前票数是%d,售票线程是%@",_tickets,[[NSThread currentThread] name]];            // 更新UI的工作,一定要放在主线程中完成            // waitUntilDone 的意思是:是否等待主线程更新完毕            [self performSelectorOnMainThread:@selector(appendTextView:) withObject:message waitUntilDone:YES];                        _tickets--;                        // 当前线程执行完毕,解锁            [_lock unlock];            // 模拟延时            if ([[[NSThread currentThread] name] isEqualToString:@"售票线程-1"]) {                [NSThread sleepForTimeInterval:0.2];            } else {                [NSThread sleepForTimeInterval:0.3];            }        }        else{            // 在退出之前需要解锁            [_lock unlock];                        // 结束信息            NSString *str = [NSString stringWithFormat:@"票已售完%@", [[NSThread currentThread] name]];            [self performSelectorOnMainThread:@selector(appendTextView:) withObject:str waitUntilDone:YES];                        break;        }    }}

4.  更新主线程UI对应的方法

- (void)appendTextView:(NSString *)text {    NSMutableString *str = [NSMutableString stringWithString:self.messageBoard.text];    [str appendFormat:@"\n%@", text];        self.messageBoard.text = str;        // 用来将文本框滚动到想要的位置    // 我们现在想要滚动到最后,这个方法的参数是一个NSRange    NSRange range = NSMakeRange(str.length, 1);    [self.messageBoard scrollRangeToVisible:range];}

这一节,我详细的介绍了线程的主要概念及NSThread的使用,下一节将为大家介绍GCD的概念及使用。

0 0
原创粉丝点击