博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
iOS:多线程NSThread的详细使用
阅读量:6585 次
发布时间:2019-06-24

本文共 5047 字,大约阅读时间需要 16 分钟。

NSThread具体使用:直接继承NSObject

NSThread:.
优点:NSThread 是轻量级的,使用简单
缺点:需要自己管理线程的生命周期、线程同步。线程同步对数据的加锁会有一定的系统开销
 
1、属性
           @property (readonly, retain) NSMutableDictionary *threadDictionary;  //线程字典
           @property double threadPriority;                                                  //线程优先级
           @property NSQualityOfService qualityOfService;                           //服务质量
           @property (copy) NSString *name;                                              //线程名字
           @property NSUInteger stackSize;                                               //堆栈大小
           @property (readonly) BOOL isMainThread;                                   //是否是主线程
           @property (readonly, getter=isExecuting) BOOL executing ;              //线程是否正在执行
           @property (readonly, getter=isFinished) BOOL finished;                 //线程是否执行完毕
           @property (readonly, getter=isCancelled) BOOL cancelled ;               //线程是否取消
 
2、通知
           将成为多线程的通知
  
          FOUNDATION_EXPORT NSString * const NSWillBecomeMultiThreadedNotification; 
           
已经成为单线程的通知
           FOUNDATION_EXPORT NSString * const NSDidBecomeSingleThreadedNotification;
           
线程将要退出的通知
           FOUNDATION_EXPORT NSString * const NSThreadWillExitNotification;
 
3、主要方法    
           
   ※当前线程
           
  + (NSThread *)currentThread;
            
 ※创建线程的类方法,并添加执行事件

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

             ※是否是多线程

             + (BOOL)isMultiThreaded;

             ※定时休眠

             + (void)sleepUntilDate:(NSDate *)date;

             ※休眠时间

             + (void)sleepForTimeInterval:(NSTimeInterval)ti;

             ※退出线程

            + (void)exit;

            ※线程优先级

           + (double)threadPriority;

           ※设置线程优先级

           + (BOOL)setThreadPriority:(double)p;

           ※显示当前栈内容(返回的是这个线程在栈中所占的地址所组成的数组)

           + (NSArray *)callStackReturnAddresses;

           ※返回栈空间的符号

           + (NSArray *)callStackSymbols;

           ※是否是主线程

           + (BOOL)isMainThread; 

           ※创建线程的实例方法,并添加执行事件

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

           ※取消线程

           - (void)cancel;

           ※启动线程

           - (void)start;

           ※线程主体要执行的方法 :thread body method

           - (void)main;

 
4、类别:@interface NSObject (NSThreadPerformAdditions)
  
 

           ※调用主线程,传入一个与主线程RunLoop循环执行有关的数组

           - (void)performSelectorOnMainThread:(SEL)aSelector withObject:(id)arg waitUntilDone:(BOOL)wait modes: (NSArray *)array;

           ※调用主线程更新UI

           - (void)performSelectorOnMainThread:(SEL)aSelector withObject:(id)arg waitUntilDone:(BOOL)wait;

           ※调用指定的线程,传入一个与线程RunLoop循环执行有关的数组

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

           ※调用指定的线程更新数据

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

            ※在后台调用线程

           - (void)performSelectorInBackground:(SEL)aSelector withObject:(id)arg;

 

具体举例如下:多线程卖票(要求:把当前票数和当前线程的名字显示在文本视图上)

1.在控件工具中拖拽一个文本视图控件并与类相关联

@property (weak, nonatomic) IBOutlet UITextView *textView;  //拖拽一个文本视图控件并与类关联

2.准备数据,并将文本视图中默认的内容置空

//准备资源    _tickets = 20;        //将默认文本视图中的内容置空    self.textView.text = @"";        //取消自动布局,用来控制文本视图的滚动    self.textView.layoutManager.allowsNonContiguousLayout = NO;

3.创建两个线程买票

//创建两个线程并启动线程    //售票线程-1    NSThread *thread1 = [[NSThread alloc]initWithTarget:self selector:@selector(saleTicket) object:nil];    //设置线程的名字,以区别不同的线程    [thread1 setName:@"售票线程-1"];    //启动线程    [thread1 start];            //售票线程-2    NSThread *thread2 = [[NSThread alloc]initWithTarget:self selector:@selector(saleTicket) object:nil];    //设置线程的名字,以区别不同的线程    [thread2 setName:@"售票线程-2"];    //启动线程    [thread2 start];

4.为主线程创建一个方法,专门用来更新并显示UI的

#pragma mark -更新UI

-(void)appendTextView:(NSString *)text{    //1.获取textView中已有的内容    NSMutableString *stringM = [[NSMutableString alloc]initWithString:self.textView.text];            //2.追加新的内容    [stringM appendString:[NSString stringWithFormat:@"\n%@",text]];    [self.textView setText:stringM];        //3.调节焦点,滚动视图    NSRange range = NSMakeRange(stringM.length, 1);    [self.textView scrollRangeToVisible:range];}

5.为买票线程创建一个方法,负责买票

#pragma mark -卖票的过程

在方法-(void)saleTicket

        {

              while (YES) {

                    执行代码如下:

              }

         }

//当票数大于0时,即if(_tickets>0)时,

操作数据并更新UI为:

//并发执行时,采用同步代码块加锁,防止数据在一个线程的操作过程中被另一个线程抢占篡改,锁必须是唯一的 @synchronized(self)
{  //拼接字符串(当前数据信息)   NSString *str = [NSString stringWithFormat:@"当前票数:%d 当前线程:%@",_tickets,[[NSThread currentThread]name  ]];                      //调用主线程,更新UI  [self performSelectorOnMainThread:@selector(appendTextView:) withObject:str waitUntilDone:YES];                       _tickets--; }

进行休眠为:

//休眠一段时间,模拟耗时操作if([[[NSThread currentThread]name] isEqualToString:@"售票线程-1"]){     [NSThread sleepForTimeInterval:0.3f];}else{     [NSThread sleepForTimeInterval:0.2f];}

//当票数小于或等于0时,更新UI,并结束线程

//拼接字符串(当前数据信息)NSString *str = [NSString stringWithFormat:@"票已经卖完 当前线程:%@",[[NSThread currentThread]name]];            //调用主线程,更新UI[self performSelectorOnMainThread:@selector(appendTextView:) withObject:str waitUntilDone:YES];            break; //结束while死循环,结束线程

演示结果如下:

当然,上面采用的是同步代码块隐式处理线程同步的问题,还可以采用显式加锁的方式来防止数据同步。

首先,声明一个NSLock的锁对象

@property (strong,nonatomic)NSLock *lock;

然后将上面的@synchronized(self)代码做修改,如下:

//在访问竞争资源前加锁[self.lock lock];            //拼接字符串(当前数据信息)NSString *str = [NSString stringWithFormat:@"当前票数:%d 当前线程:%@",_tickets,[[NSThread currentThread]name]];            //调用主线程,更新UI[self performSelectorOnMainThread:@selector(appendTextView:) withObject:str waitUntilDone:YES];            _tickets--;            //访问完竞争资源马上解锁[self.lock unlock];

演示结果相同:

 

 

 

 

 

 

 

程序猿神奇的手,每时每刻,这双手都在改变着世界的交互方式!
分类: 
本文转自当天真遇到现实博客园博客,原文链接:http://www.cnblogs.com/XYQ-208910/p/4857689.html,如需转载请自行联系原作者
你可能感兴趣的文章
[转]asp.net权限认证:摘要认证(digest authentication)
查看>>
maven入门(9)Maven常用命令
查看>>
企业敏捷转型试运行
查看>>
MVC发送邮件
查看>>
和同事合作开发,使用局域网 git创建本地仓库
查看>>
【java】乱码处理+编码转化+判断字符串编码方式
查看>>
【Android】ListView 优化
查看>>
本地环境phpStorm10+XDebug配置和断点调试
查看>>
HDOJ 4251 The Famous ICPC Team Again
查看>>
POJ 3132 & ZOJ 2822 Sum of Different Primes(dp)
查看>>
SharePoint 2016 工作流报错“未安装应用程序管理共享服务代理”
查看>>
MyBatis源码解析【6】SqlSession运行
查看>>
java.lang.ClassNotFoundException:org.springframework.web.context.ContextLoaderListener问题解决
查看>>
第一章: 当前主流的小型嵌入式 GUI
查看>>
【剑指Offer面试题】 九度OJ1368:二叉树中和为某一值的路径
查看>>
黑幕背后的Autorelease
查看>>
怎样防止应用因获取IDFA被AppStore拒绝
查看>>
c#用webkit内核支持html5
查看>>
Java -- POI -- 入门使用以及简单介绍
查看>>
jQuery中的append()和prepend(),after()和before()的差别
查看>>