【iOS】pthread、NSThread

2024-05-04 07:44
文章标签 ios pthread nsthread

本文主要是介绍【iOS】pthread、NSThread,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

文章目录

  • 前言
  • 一、pthread 使用方法
    • pthread 其他相关方法
  • 二、 NSThread
    • 创建、启动线程
    • 线程相关用法
    • 线程状态控制方法
    • NSThread 线程安全和线程同步
    • 场景
  • 线程的状态转换


前言

五一这两天准备将GCD相关的知识完,同时NSOperationNSThread、pthread也是相关知识,这一篇文章主要讲解NSThread、pthread的学习

pthread是一套用C语言编写的多线程API,可以在Unix / Linux / Windows 等系统跨平台使用,尽管现在已经不常用,但是还是可以了解

一、pthread 使用方法

1、导入头文件#import <pthread.h>
2、其次创建线程执行任务

void* run(void *param) {NSLog(@"%@", [NSThread currentThread]);return nil;
}- (void)viewDidLoad {[super viewDidLoad];pthread_t thread;pthread_create(&thread, NULL, run, NULL);pthread_detach(thread);
}

pthread_create(&thread, NULL, run, NULL); 中各项参数含义:

  • 第一个参数&thread是线程对象,指向线程标识符的指针
  • 第二个是线程属性,可赋值NULL
  • 第三个run表示指向函数的指针(run对应函数里是需要在新线程中执行的任务)
  • 第四个是运行函数的参数,可赋值NULL

这里有一个注意点: 在 CObjective-C 中,线程的启动函数需要具备特定的签名。对于
pthread_create,期望的线程函数必须返回一个 void * 并接受一个 void *
参数。具体来说,函数类型应该是:
void *ThreadFunction(void *arg);

pthread 其他相关方法

pthread_create() //创建一个线程
pthread_exit() //终止当前线程
pthread_cancel() //中断另外一个线程的运行
pthread_join() //阻塞当前的线程,直到另外一个线程运行结束
pthread_attr_init() //初始化线程的属性
pthread_attr_setdetachstate() //设置脱离状态的属性(决定这个线程在终止时是否可以被结合)
pthread_attr_getdetachstate() //获取脱离状态的属性
pthread_attr_destroy() //删除线程的属性
pthread_kill() //向线程发送一个信号

二、 NSThread

NSThread是苹果官方提供的,使用起来更加面向对象,简单易用,可以直接操作线程对象

我们在开发的过程中偶尔使用 NSThread。比如我们会经常调用[NSThread currentThread]来显示当前的进程信息。

创建、启动线程

  • 先创建线程再启动线程
    // 1. 创建线程NSThread *thread = [[NSThread alloc] initWithTarget:self selector:@selector(run) object:nil];// 2. 启动线程[thread start];    // 线程一启动,就会在线程thread中执行self的run方法// 新线程调用方法,里边为需要执行的任务
- (void)run {NSLog(@"%@", [NSThread currentThread]);
}
  • 创建线程后自动启动线程
// 1. 创建线程后自动启动线程
[NSThread detachNewThreadSelector:@selector(run) toTarget:self withObject:nil];// 新线程调用方法,里边为需要执行的任务- (void)run {NSLog(@"%@", [NSThread currentThread]);
}
  • 隐式创建并启动线程
// 1. 隐式创建并启动线程
[self performSelectorInBackground:@selector(run) withObject:nil];// 新线程调用方法,里边为需要执行的任务
- (void)run {NSLog(@"%@", [NSThread currentThread]);
}

线程相关用法

// 获得主线程
+ (NSThread *)mainThread;    // 判断是否为主线程(对象方法)
- (BOOL)isMainThread;// 判断是否为主线程(类方法)
+ (BOOL)isMainThread;    // 获得当前线程
NSThread *current = [NSThread currentThread];// 线程的名字——setter方法
- (void)setName:(NSString *)n;    // 线程的名字——getter方法
- (NSString *)name;    

线程状态控制方法

启动线程方法:

- (void)start;
// 线程进入就绪状态 -> 运行状态。当线程任务执行完毕,自动进入死亡状态

阻塞(暂停)线程方法:

+ (void)sleepUntilDate:(NSDate *)date;
+ (void)sleepForTimeInterval:(NSTimeInterval)ti;
// 线程进入阻塞状态

强制停止线程:

+ (void)exit;
// 线程进入死亡状态

NSThread 线程安全和线程同步

  • 线程安全:如果你的代码所在的进程中有多个线程在同时运行,而这些线程可能会同时运行这段代码。如果每次运行结果和单线程运行的结果是一样的,而且其他的变量的值也和预期的是一样的,就是线程安全的。

如果每个线程对于全局变量,静态变量都只有读取的操作,说明变量是线程安全的,如果使用多线程进行读写操作,就必须要考虑线程同步

  • 线程同步:有两个线程A与B,A与B相互依赖,A 执行到一定程度时要依靠线程 B 的某个结果,于是停下来,示意 B 运行;B 依言执行,再将结果给 A;A 再继续操作。

例子:
两个人在一起聊天。两个人不能同时说话,避免听不清(操作冲突)。等一个人说完(一个线程结束操作),另一个再说(另一个线程再开始操作)。

场景

我们用一个经典的模拟售票的例子实现 NSThread 线程安全和解决线程同步问题。

场景:总共有50张火车票,有两个售卖火车票的窗口,一个是北京火车票售卖窗口,另一个是上海火车票售卖窗口。两个窗口同时售卖火车票,卖完为止。

如果线程非安全代码如下:

-(void)initTicketStatusNotSafe {// 1. 设置剩余火车票为 50self.ticketSurplusCount = 50;// 2. 设置北京火车票售卖窗口的线程NSThread *ticketSaleWindow1 = [[NSThread alloc]initWithTarget:self selector:@selector(saleTicketNotSafe) object:nil];ticketSaleWindow1.name = @"北京火车票售票窗口";// 3. 设置上海火车票售卖窗口的线程NSThread *ticketSaleWindow2 = [[NSThread alloc]initWithTarget:self selector:@selector(saleTicketNotSafe) object:nil];ticketSaleWindow2.name = @"上海火车票售票窗口";// 4. 开始售卖火车票[ticketSaleWindow1 start];[ticketSaleWindow2 start];}- (void)saleTicketNotSafe {while (1) {//如果还有票,继续售卖if ([NSThread currentThread] != [NSThread mainThread]) {if (self.ticketSurplusCount > 0) {self.ticketSurplusCount --;NSLog(@"%@", [NSString stringWithFormat:@"剩余票数:%ld 窗口:%@", self.ticketSurplusCount, [NSThread currentThread].name]);[NSThread sleepForTimeInterval:0.2];}//如果已卖完,关闭售票窗口else {NSLog(@"所有火车票均已售完");break;}}}
}

在这里插入图片描述
可以看到票序是混乱的

因为如果不对线程进行加锁可能在同一时间两个线程会访问同一资源,会造成当前结果,因此我们需要在一个线程执行该操作的时候,不允许其他线程进行操作

iOS 实现线程加锁有很多种方式。@synchronized、 NSLock、NSRecursiveLock、NSCondition、NSConditionLock、pthread_mutex、dispatch_semaphore、OSSpinLock、atomic(property) set/ge等等各种方式。为了简单起见,这里不对各种锁的解决方案和性能做分析,只用最简单的@synchronized来保证线程安全,从而解决线程同步问题。

线程安全代码:

- (void)saleTicketNotSafe {while (1) {//如果还有票,继续售卖@synchronized (self) {if ([NSThread currentThread] != [NSThread mainThread]) {if (self.ticketSurplusCount > 0) {self.ticketSurplusCount --;NSLog(@"%@", [NSString stringWithFormat:@"剩余票数:%ld 窗口:%@", self.ticketSurplusCount, [NSThread currentThread].name]);[NSThread sleepForTimeInterval:1];}//如果已卖完,关闭售票窗口else {NSLog(@"所有火车票均已售完");break;}}}}
}

在这里插入图片描述

线程的状态转换

当我们新建一条线程NSThread *thread = [[NSThread alloc] initWithTarget:self selector:@selector(run) object:nil]; ,在内存中的表现为:
在这里插入图片描述
当调用[thread start];后,系统把线程对象放入可调度线程池中,线程对象进入就绪状态,如下图所示。
在这里插入图片描述

当然,可调度线程池中,会有其他的线程对象
在这里插入图片描述

下边我们来看看当前线程的状态转换。
如果我们调用当前线程对象,当前线程就会进入运行状态,如果调度了其他线程对象,那么当前线程就会回到就绪状态

  • 如果CPU现在调度当前线程对象,则当前线程对象进入运行状态,如果CPU调度其他线程对象,则当前线程对象回到就绪状态。
  • 如果CPU在运行当前线程对象的时候调用了sleep方法或者等待同步锁,则当前线程对象就进入了阻塞状态,等到sleep到时或者得到同步锁,则回到就绪状态。
  • 如果CPU在运行当前线程对象的时候线程任务执行完毕或者异常强制退出,则当前线程对象进入死亡状态。
    在这里插入图片描述

这篇关于【iOS】pthread、NSThread的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/958679

相关文章

安卓链接正常显示,ios#符被转义%23导致链接访问404

原因分析: url中含有特殊字符 中文未编码 都有可能导致URL转换失败,所以需要对url编码处理  如下: guard let allowUrl = webUrl.addingPercentEncoding(withAllowedCharacters: .urlQueryAllowed) else {return} 后面发现当url中有#号时,会被误伤转义为%23,导致链接无法访问

【iOS】MVC模式

MVC模式 MVC模式MVC模式demo MVC模式 MVC模式全称为model(模型)view(视图)controller(控制器),他分为三个不同的层分别负责不同的职责。 View:该层用于存放视图,该层中我们可以对页面及控件进行布局。Model:模型一般都拥有很好的可复用性,在该层中,我们可以统一管理一些数据。Controlller:该层充当一个CPU的功能,即该应用程序

iOS剪贴板同步到Windows剪贴板(无需安装软件的方案)

摘要 剪贴板同步能够提高很多的效率,免去复制、发送、复制、粘贴的步骤,只需要在手机上复制,就可以直接在电脑上 ctrl+v 粘贴,这方面在 Apple 设备中是做的非常好的,Apple 设备之间的剪贴板同步功能(Universal Clipboard)确实非常方便,它可以在 iPhone、iPad 和 Mac 之间无缝传输剪贴板内容,从而大大提高工作效率。 但是,iPhone 如何和 Wind

iOS项目发布提交出现invalid code signing entitlements错误。

1、进入开发者账号,选择App IDs,找到自己项目对应的AppId,点击进去编辑, 2、看下错误提示出现  --Specifically, value "CVYZ6723728.*" for key "com.apple.developer.ubiquity-container-identifiers" in XX is not supported.-- 这样的错误提示 将ubiquity

我的第一次份实习工作-iOS实习生-第三个月

第三个月 这个月有一个考核项目,是一个电子书阅读器,组长说很重要,是我的实习考核项目。 我的项目XTReader,这是我参考网上的一些代码,和模仿咪咕阅读做的,功能还不完善,数据的部分是用聚合数据做的。要收费的。   还有阅读页面,基本功能实现了一下。使用了autolayout,自适应布局,也是第一次用网络,第一次用数据库,第一次用自动布局。还有很多不足。 做了一周多,有个问题一直没

我的第一次份实习工作-iOS实习生-公司使用过的软件

bittorrentsync 素材,文件同步软件 cornerstone svn 软件开发合作 mark man 测量坐标的软件 SQLLite Manager 数据库操作软件

我的第一次份实习工作-iOS实习生-第二个月

第二个月 来公司过了一个月了。每天早上9点上班,到晚上6.30下班,上下班要指纹打卡,第一个月忘了打卡好多次(),然后还要去补打卡单。公司这边还安排了,工资卡办理,招商银行卡。开了一次新员工大会,认识了公司的一些过往,公司的要求等,还加了一下公司的企业QQ,还有其他的羽毛球群,篮球群。我加了下羽毛球群,也去打了一两次。第二个月的感受,感觉跟组里面的交流跟沟通都好少,基本上还有好多人不认识。想想也

我的第一次份实习工作-iOS实习生-第一个月

实习时间:2015-08-20 到 2015-12-25  实习公司;福建天棣互联有限公司 实习岗位:iOS开发实习生 第一个月: 第一天来公司,前台报道后,人资带我去我工作的地方。到了那,就由一个组长带我,当时还没有我的办公桌,组长在第三排给我找了一个位置,擦了下桌子,把旁边的准备的电脑帮我装了下,因为学的是iOS,实习生就只能用黑苹果了,这是我实习用的电脑。 帮我装了一下电脑后,开机

iOS如何隐藏系统状态栏

这里主要说明一下iOS7系统给状态栏的适配及隐藏带来的改变。 变化一: 不隐藏状态栏的情况下,StatusBar会直接显示在当前页面上,当前页面的会延伸到 StatusBar下方,顶到最上头。 这种显示方式在iOS7上是无法改变的,也无法通过设置或者配置类达到iOS6的状态栏效果。       所以在iOS7上进行页面布局的时候要考虑

SylixOS pthread_join退出

1 问题描述 在移植中间件过程中,在SylixOS下调用pthread_join时,如果线程在pthread_join等待之前结束,则线程返回无效线程错误值。在Linux下这种调用会正常返回。两种实现是有差别的,实现的原理分别如下。 2 函数实现机制 2.1 实现机制 在SylixOS下调用pthread_join时,如果线程在pthread_join等待之前结束,线程返回无效线程错误标志