NSThread-详解

2019-03-22  本文已影响0人  Q2我没有疯

当你想在线程中执行一个很长的任务,但又不希望它阻塞应用程序其余部分的执行时,子线程尤其有用,你可以将任务放在子线程中来执行,避免阻塞应用程序的主线程,让主线程处理用户界面和与事件相关的操作,子线程用于将大型任务划分为几个较小的任务,这能会使多核计算机上的性能提高。


NSThread使用

  1. 这种创建方式需要手动启动线程
- (void)viewDidLoad {
    [super viewDidLoad];
    // 创建一条线程(方式一)
    NSThread *thread = [[NSThread alloc] initWithTarget:self selector:@selector(runThread:) object:@"我是一条线程"];
    // 启动线程
    [thread start];
}
  1. 以下几种方式创建线程会自动启动线程,但是出了方式二以外的几种创建方式都无法对线程进行详细的设置。
// 方式二
   NSThread *thread = [[NSThread alloc] initWithBlock:^{
       
   }];
// 方式三
   [NSThread detachNewThreadWithBlock:^{
          NSLog(@"thread=%@-------",[NSThread currentThread]);
   }];
// 方式四
   [NSThread detachNewThreadSelector:@selector(runThread:) toTarget:self withObject:@"线程"];
// 方式五
   [self  performSelectorInBackground:@selector(runThread:) withObject:@"线程"];

// 优先级 0.0 ~ 1.0 默认 0.5 数值越大优先级越高
@property double threadPriority ; 

/** NSQualityOfService:
  NSQualityOfServiceUserInteractive:最高优先级,主要用于提供交互UI的操作,比如处理点击事件,绘制图像到屏幕上
  NSQualityOfServiceUserInitiated:次高优先级,主要用于执行需要立即返回的任务
  NSQualityOfServiceDefault:默认优先级,当没有设置优先级的时候,线程默认优先级
  NSQualityOfServiceUtility:普通优先级,主要用于不需要立即返回的任务
  NSQualityOfServiceBackground:后台优先级,用于完全不紧急的任务
*/
@property NSQualityOfService qualityOfService; 

// 线程名称(区别多条线程)
@property (nullable, copy) NSString *name;

// 线程正在执行
@property (readonly, getter=isExecuting) BOOL executing;

// 线程执行结束
@property (readonly, getter=isFinished) BOOL finished;

// 线程是否可以取消
@property (readonly, getter=isCancelled) BOOL cancelled;
-(void)start; // 启动线程

-(BOOL)isMainThread; // 是否为主线程

-(void)setName:(NSString *)n; // 设置线程名称

-(void)cancel ;// 取消线程

-(void)isExecuting; // 判断线程是否正在执行

-(void)isCancelled; // 判断线程是否撤销

-(void)isFinished; // 判断线程是否已经结束

+(void)currentThread; // 获取当前线程

+(BOOL)isMultiThreaded;  // 当前代码运行所在线程是否是子线程

+(void)sleepUntilDate:(NSDate *)date;  //当前代码所在线程睡到指定时间

+(void)sleepForTimeInterval:(NSTimeInterval)ti; //当前线程睡多长
时间

+(void)exit; // 退出当前线程

当线程中的任务执行完成过后被释放


线程的安全

总共有100张电影票,当售票员01和02同时获取到余票为一百张时,01卖出了80张余票为20张,02卖出了21张余票为79张,实际上他们卖出了101张但是总票数只有100张,这样就多出一个人没法看电影,这就是引发数据错乱。


#import "ViewController.h"

@interface ViewController ()
@property (nonatomic,strong) NSThread *threadA;
@property (nonatomic,strong) NSThread *threadB;
@property (nonatomic,strong) NSThread *threadC;

@property (nonatomic,assign) NSInteger totalCount;
@end

@implementation ViewController

- (void)viewDidLoad {
    [super viewDidLoad];
    
    // 总共设置100 票
    self.totalCount = 100;
    
    self.threadA = [[NSThread alloc] initWithTarget:self selector:@selector(runThread:) object:nil];
    self.threadB = [[NSThread alloc] initWithTarget:self selector:@selector(runThread:) object:nil];
    self.threadC = [[NSThread alloc] initWithTarget:self selector:@selector(runThread:) object:nil];
    
    self.threadA.name = @"售票员A";
    self.threadB.name = @"售票员B";
    self.threadC.name = @"售票员C";
    
    [self.threadA start];
    [self.threadB start];
    [self.threadC start];

}

-(void)runThread:(id)obj{
    while (1) {
        NSInteger count = self.totalCount;
        if (count>0) {
            for (int i = 0; i<1000; i++) { // 模拟售票时间
                self.totalCount = count - 1;
            }
            NSLog(@"%@卖了一张票还剩%zd",[NSThread currentThread].name,self.totalCount);
        }else{
            NSLog(@"售完了");
            break;
        }
    }
}
@end
输出结果.png

-(void)runThread:(id)obj{
 
    while (1) {
        // 锁:必须是全局唯一的
        @synchronized (self) {  // 互斥锁
            NSInteger count = self.totalCount;
            if (count>0) {
                for (int i = 0; i<1000; i++) { // 模拟售票时间
                    self.totalCount = count - 1;
                }
                NSLog(@"%@卖了一张票还剩%zd",[NSThread currentThread].name,self.totalCount);
            }else{
                NSLog(@"售完了");
                break;
            }
        }
    }
      
}
互斥锁结果.png

非原子属&性原子

线程间通信

// 从当前线程切换到主线程中
-(void)performSelectorOnMainThread:(SEL)aSelector
                        withObject:(id)arg
                     waitUntilDone:(BOOL)wait;
    
// 从当前线程切换到指定的线程
-(void)performSelector:(SEL)aSelector
              onThread:(NSThread *)thr
            withObject:(id)arg
         waitUntilDone:(BOOL)wait;
上一篇下一篇

猜你喜欢

热点阅读