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 = ; //将默认文本视图中的内容置空
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, );
[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];

演示结果相同:

iOS:多线程NSThread的详细使用的更多相关文章

  1. iOS多线程 NSThread/GCD/NSOperationQueue

    无论是GCD,NSOperationQueue或是NSThread, 都没有线程安全 在需要同步的时候需要使用NSLock或者它的子类进行加锁同步 "] UTF8String], DISPA ...

  2. ios多线程NSThread

    1.简介: 1.1 iOS有三种多线程编程的技术,分别是: 1..NSThread 2.Cocoa NSOperation (iOS多线程编程之NSOperation和NSOperationQueue ...

  3. iOS多线程NSThread和GCD

    在iOS中啊  其实有多种方法实现多线程 这里只记录两个比较常用的  或者说我比较常用的 一个就是BSThread 另一个就是一听名字就比较霸气的妇孺皆知的GCD 先说一下NSThread吧 这个方式 ...

  4. IOS 多线程 NSThread

    一个正在运行的应用程序是一个进程,一个进程会默认开启一个主线程,但是在主线程中的操作是串行的,也就是当有多个任务同时需要完成的时候,是按照顺序一个个执行.因此,为了提高效率,会在进程中开启多个线程,每 ...

  5. iOS 多线程NSThread理解与场景示例

    NSThread是相对GCD和NSOperationQuene而言,比较轻量级的一种多线程处理方式. 但同时,它的弊端就是需要自己管理线程的生命周期,以及线程同步:而另外两种不需要自己管理. 常见方法 ...

  6. IOS 多线程-NSThread 和线程状态

    @interface HMViewController () - (IBAction)btnClick; @end @implementation HMViewController - (void)v ...

  7. iOS多线程的详情使用示例--简进祥

    大家都知道,在开发过程中应该尽可能减少用户等待时间,让程序尽可能快的完成运算.可是无论是哪种语言开发的程序最终往往转换成汇编语言进而解释成机器码来执行.但是机器码是按顺序执行的,一个复杂的多步操作只能 ...

  8. iOS多线程开发

    概览 大家都知道,在开发过程中应该尽可能减少用户等待时间,让程序尽可能快的完成运算.可是无论是哪种语言开发的程序最终往往转换成汇编语言进而解释成机器码来执行.但是机器码是按顺序执行的,一个复杂的多步操 ...

  9. iOS 多线程详解

    iOS开发 多线程 概览 机器码是按顺序执行的,一个复杂的多步操作只能一步步按顺序逐个执行.改变这种状况可以从两个角度出发: 对于单核处理器,可以将多个步骤放到不同的线程,这样一来用户完成UI操作后其 ...

随机推荐

  1. Linux Python apache的cgi配置

    一.找到安装Apache的目录/usr/local/apache2/conf,并对httpd.conf配置文件进行修改 1.加载cgi模块 去掉注释: LoadModule cgid_module m ...

  2. window.screen.height和window.screen.availHeight和document.body.clientHeight和document.documentElement.clientHeight

    说这几个属性前 我说一下我的设备 我的设备有两个,一个高度为1080的显示器,一个高度为800的电脑 第一种:window.screen.height 这个方法是获取用户电脑屏幕的高度,是不关浏览器或 ...

  3. 【机器学习】k-近邻算法应用之手写数字识别

    上篇文章简要介绍了k-近邻算法的算法原理以及一个简单的例子,今天再向大家介绍一个简单的应用,因为使用的原理大体差不多,就没有没有过多的解释. 为了具有说明性,把手写数字的图像转换为txt文件,如下图所 ...

  4. Apache配置基于端口号的虚拟主机 Apache virtual host configuration is based on the port

    有可能只有一个ip出口,但却有多个项目,那么就需要基于端口号架设虚拟主机. Step 1: 检查是否开启 httpd-vhosts.conf apache/conf/httpd.conf文件 # Vi ...

  5. LoadRunner运行中的mmdrv和mdrv

    在LoadRunner运行脚本过程中,在任务管理器中我们可以看到有一个或多个名为“mmdrv”的进程在运行,与此同时当我们查看LoadRunner\bin目录下的文件时还会看到一个“mdrv.exe” ...

  6. Ionic-wechat项目边开发边学(三):自定义样式,指令,服务

    摘要 上一篇文章主要介绍了一个ionic项目的标准目录结构,header标签的使用,以及页面之间的切换.这篇文章实现的功能有: 消息数据的获取, 消息列表的展示, 消息标为已读/未读, 主要涉及的到的 ...

  7. 转:Fuzzing Apache httpd server with American Fuzzy Lop + persistent mode

    Fuzzing Apache httpd server with American Fuzzy Lop + persistent mode 小结:AFL主要以文件作为输入进行fuzz,本文介绍如何对网 ...

  8. 关于hadoop处理大量小文件情况的解决方法

    小文件是指那些size比HDFS的block size(默认64m)小的多的文件.任何一个文件,目录和bolck,在HDFS中都会被表示为一个object存储在namenode的内存中,每一个obje ...

  9. 2017CCPC 杭州 J. Master of GCD【差分标记/线段树/GCD】

    给你一个n个初始元素都为1的序列和m个询问q. 询问格式为:l r x(x为2or3) 最后求1~n所有数的GCD GCD:把每个数分别分解质因数,再把各数中的全部公有质因数提取出来连乘,所得的积就是 ...

  10. 总结分析Java常见的四种引用

    从JDK1.2版本开始,把对象的引用分为四种级别,从而使程序能更加灵活的控制对象的生命周期.这四种级别由高到低依次为:强引用.软引用.弱引用和虚引用. 1.强引用 本章前文介绍的引用实际上都是强引用, ...