多线程技术是有多套解决方案的,那么我们该如何选择呢?

技术方案   简介 语言 线程生命周期 使用频率
pthread

1.一套通用的多线程API

2.适用于UNIX,linux,windows等

3.跨平台,可移植

4.使用难度较高

C 程序员管理 几乎不用
NSThread

1.更加面向对象

2.简单易用,可直接操作线程对象

OC 程序员管理 偶尔使用
GCD  

1.用来替代NSThread等线程技术

2.充分利用设备的多核

C 自动管理 经常使用
NSOperation

1.基于GCD(底层是GCG)

2.比GCD多了一些更简单适用的功能

3.使用更加面向对象

OC 自动管理 经常使用

我们来看看具体的使用,先来说pthread。他表示可移植操作系统接口(portable opration system interface)posix

1.pthread技术

pthread是posix的多线程开发框架,是跨平台的C语言框架。

这个我们可以不用去关系,接下来我们看NSThread技术。

我们来看代码:

  1. - (void)viewDidLoad {
  2. [super viewDidLoad];
  3. // Do any additional setup after loading the view, typically from a nib.
  4. NSLog(@"主线程",[NSThread currentThread]);
  5.  
  6. //方法1:通过NSThread的对象方法
  7. NSThread *thread = [[NSThread alloc] initWithTarget:self selector:@selector(demo:) object:@"方式1"];
  8. [thread start];
  9.  
  10. //方法2:没有start方法,隐式创建并且启动,但没有线程名字。
  11. [self performSelectorInBackground:@selector(demo:) withObject:@"方法2"];
  12.  
  13. //方法3 detachNewThreadSelectora方法不需要手动启动,会自动启动并执行selector方法
  14. [NSThread detachNewThreadSelector:@selector(demo:) toTarget:self withObject:@"方法3"];
  15. }
  16.  
  17. -(void)demo:(NSString*)str{
  18. NSLog(@"%@, %@",str,[NSThread currentThread]);
  19. }

  打印出的结果如下:

2019-03-28 15:28:12.352283+0800 wftest[1631:26090] 主线程

2019-03-28 15:28:12.353628+0800 wftest[1631:26443] 方式1, <NSThread: 0x600002736540>{number = 3, name = (null)}

2019-03-28 15:28:12.353680+0800 wftest[1631:26445] 方法3, <NSThread: 0x600002736740>{number = 5, name = (null)}

2019-03-28 15:28:12.361688+0800 wftest[1631:26444] 方法2, <NSThread: 0x600002736500>{number = 4, name = (null)}


接着,我们来看看线程的属性。

1.name.线程的名字。我们看到上面打印出来的LOG。发现线程都没有名字的。现在我们给thread加上名字。

在第一个方式里,加上thread.name = @"thread1";再进行打印:

2019-03-28 15:35:17.221996+0800 wftest[1911:30827] 主线程

2019-03-28 15:35:17.222669+0800 wftest[1911:30951] 方法3, <NSThread: 0x600003963980>{number = 5, name = (null)}

2019-03-28 15:35:17.222680+0800 wftest[1911:30949] 方式1, <NSThread: 0x600003963780>{number = 3, name = thread1}

2019-03-28 15:35:17.224179+0800 wftest[1911:30950] 方法2, <NSThread: 0x600003963740>{number = 4, name = (null)}

我们发现,第一个方式里的thread已经有了名字。

但是,你也许注意到了。我们两次打印,线程的运行顺序,却不一样。

接着,我们看线程的另一个属性,threadPriority也就是线程的优先级。

取值0-1.0

1.0表示优先级最高

0表示最低

默认的值为0.5

此时我们再给代码加上优先级看下。

  1. - (void)viewDidLoad {
  2. [super viewDidLoad];
  3. // Do any additional setup after loading the view, typically from a nib.
  4. NSLog(@"主线程",[NSThread currentThread]);
  5.  
  6. //方法1:通过NSThread的对象方法
  7. NSThread *thread = [[NSThread alloc] initWithTarget:self selector:@selector(demo:) object:@"方式1"];
  8. thread.name = @"thread1";
  9. thread.threadPriority = 1.0;
  10. [thread start];
  11.  
  12. //方法2:没有start方法,隐式创建并且启动,但没有线程名字。
  13. [self performSelectorInBackground:@selector(demo:) withObject:@"方法2"];
  14.  
  15. //方法3 detachNewThreadSelectora方法不需要手动启动,会自动启动并执行selector方法
  16. [NSThread detachNewThreadSelector:@selector(demo:) toTarget:self withObject:@"方法3"];
  17. }
  18.  
  19. -(void)demo:(NSString*)str{
  20. NSLog(@"%@, %@",str,[NSThread currentThread]);
  21. }

  看打印结果:

2019-03-28 15:43:21.467869+0800 wftest[2178:35176] 主线程

2019-03-28 15:43:21.468453+0800 wftest[2178:35234] 方式1, <NSThread: 0x600002ce3780>{number = 3, name = thread1}

2019-03-28 15:43:21.469110+0800 wftest[2178:35236] 方法3, <NSThread: 0x600002ce3980>{number = 5, name = (null)}

2019-03-28 15:43:21.470449+0800 wftest[2178:35235] 方法2, <NSThread: 0x600002ce3740>{number = 4, name = (null)}

可以看到,方法1里的thread果然被率先执行了。

再来看thread的另一个属性,stacksize 栈区大小。

isMainThread是否是主线程

再来看有关资源共享引发的资源抢夺问题。

因为多个线程共享资源,当多个线程共同访问同一块资源时候,比如同一个对象,同一个数据,就会引发数据错乱问题,比如售票系统。

这个时候就需要我们用到线程中的互斥锁了。我们来看代码:

  1. - (void)viewDidLoad {
  2. [super viewDidLoad];
  3. // Do any additional setup after loading the view, typically from a nib.
  4. _count = 50;
  5. NSThread *thread1 = [[NSThread alloc] initWithTarget:self selector:@selector(sellTickets) object:nil];
  6. thread1.name = @"thread1";
  7. [thread1 start];
  8.  
  9. NSThread *thread2 = [[NSThread alloc] initWithTarget:self selector:@selector(sellTickets) object:nil];
  10. thread2.name = @"thread2";
  11. [thread2 start];
  12.  
  13. }
  14.  
  15. -(void)sellTickets{
  16. while (YES) {
  17. //互斥锁
  18. @synchronized (self) {
  19. if(_count>0){
  20. _count = self.count-1;
  21. NSLog(@"剩余票数:%ld--------%@",_count,[NSThread currentThread]);
  22. }else{
  23. NSLog(@"抱歉,票已经售完");
  24. break;
  25. }
  26. }
  27. }
  28. }

  这里面有个一个互斥锁,互斥锁的意思就是说,当发现有其他的线程正在执行这段被锁定的代码的时候,线程会进入休眠状态。等待其他线程执行完毕后,锁打开,这个休眠的线程就会被唤醒。

实际上,除了互斥锁之外,还有一个锁,是自旋锁。自旋锁的意思就是说当发现其他线程正在执行这段被锁定的代码的时候,线程会以死循环的方式,一直等待锁定代码执行完成。

线程安全:

当多个线程进行读写操作的时候,仍然能够得到一个正确的结果。被称为线程安全,要实现线程安全,就必须使用锁。

为了得到更好的用户体验,所以,UIKIT不是线程安全的,所以更新UI的操作,必须到主线程去执行。主线程又被称为UI线程。

有关NSTread的内容就说到这里,下次说IOS多线程中,常用的GCD技术。

ios高级开发之多线程(二)NSThread技术的更多相关文章

  1. 移动开发在路上-- IOS移动开发系列 多线程二

    最近太忙没太多的时间,忙碌的码农生活空下来一点时间,都会挤出来看一些技术或者咨询的文章,废话不多说,直奔主题. 接着上一次的继续说. 定时器在多线程的使用 NSRunLoop 是线程相关的基础框架的一 ...

  2. IOS高级开发之多线程(四)NSOperation

    1.什么是NSOperation,NSOperationQueue? NSOperation是一个抽象的基类,表示一个独立的计算单元,可以为子类提供有用且线程安全的建立状态,优先级,依赖和取消等操作. ...

  3. ios高级开发之多线程(三)GCD技术

    GCD是基于C的API,它是libdispatch的的市场名称.而libdispatch作为Apple公司的一个库,为并发代码在多核硬件(跑IOS或者OS X)上执行提供有力支持. 那么我们为什么要用 ...

  4. ios高级开发之多线程(一)

    1.概念: 多线程(multithreading)到底是什么呢,它是指在软件或者硬件上实现多个线程并发执行的技术.具有多线程能力的计算机因有硬件的支持,而能够在同一时间执行多个线程,进而提升整体处理性 ...

  5. IOS高级开发之多线程(五)NSOperation 2

    接着看NSOperation.NSOperationQueue线程间的通信: 应用场景:比如我们经常把一些耗时的操作比如下载图片放在子线程,那么当这个完成之后,我们就需要回到主线程,这个时候就需要用到 ...

  6. IOS 高级开发 KVC(二)

    前一篇博客最后介绍了KVC 再json 转模型时遇到一些问题.今天接着来介绍KVC 的其他用法.其实我们在一开始的时候就一直再强调命名的重要性.命名规范是KVC 存活的基础.如果没有这个条件支撑,那么 ...

  7. IOS 高级开发 runtime(二)

    二.移魂大法 使用runtime还可以交换两个函数.先贴上代码和执行结果. #import <Foundation/Foundation.h> @interface DZLPerson : ...

  8. (转发)IOS高级开发~Runtime(二)

    一些公用类: @interface ClassCustomClass :NSObject{ NSString *varTest1; NSString *varTest2; NSString *varT ...

  9. iOS开发之多线程(NSThread、NSOperation、GCD)

    整理一些多线程相关的知识. 并行 & 并发 1.并行:并行是相对于多核而言的,几个任务同时执行.2.并发:并发是相对于单核而言的,几个任务之间快速切换运行,看起来像是"同时" ...

随机推荐

  1. 剑指offer-扑克牌顺子

    题目描述 LL今天心情特别好,因为他去买了一副扑克牌,发现里面居然有2个大王,2个小王(一副牌原本是54张^_^)...他随机从中抽出了5张牌,想测测自己的手气,看看能不能抽到顺子,如果抽到的话,他决 ...

  2. abap test seam 和 TEST-INJECTION

    TEST-SEAM 和 TEST-INJECTION 一块儿使用 可以模拟出调用方法的return,exporting,chaning值.  例如: 1: 假设有一个类zcl_demo_input,该 ...

  3. LeetCode 5 最长对称串

    LeetCode 5 最长对称串 最早时候做这道题的时候还是用Java写的,用的是字符串匹配的思路,一直Time Limit Exceeded.甚至还想过用KMP开优化子串查找. public cla ...

  4. React 学习过程中常见的错误

    1,  react报错Module not found: Error: Can't resolve     解决:  一般是加载文件的路径写错了:      

  5. requests 可以玩接口自动化测试,爬虫也是可以滴

    import requests #1.带参的get请求: url ='URL_你的' requests.get(url,params={"key":"value" ...

  6. php----------const 定义的常量和define()定义的常量的区别?

    用法一:const用于类成员变量,一经定义不可修改,define用于全局常量,不可用于类成员变量的定义,const可在类中使用也可以在类外面使用,define不能. 定义:const 常量名=值; 没 ...

  7. mysql 5.7 配置文件说明

    1.配置文件样例 [client] #password= socket=/data/var/mysql/mysql.sock [mysqld_safe] pid-file=/data/var/mysq ...

  8. Centos7 下yum安装mysql

  9. BELLMEN-FORD普通

    #include <iostream> using namespace std; int m, n, u[100010], v[100010], w[100010];int check;i ...

  10. liunx驱动----点亮LED

    自动挂接根文件系统(直接从NFS启动) 修改uboot命令行 把 bootargs=noinitrd root=/dev/mtdblock3 init=/linuxrc console=ttySAC0 ...