【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在运行当前线程对象的时候线程任务执行完毕或者异常强制退出,则当前线程对象进入死亡状态。
    在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.xdnf.cn/news/1411079.html

如若内容造成侵权/违法违规/事实不符,请联系一条长河网进行投诉反馈,一经查实,立即删除!

相关文章

向量体系结构(4):多条车道内存组

笔记来源《计算机体系结构 量化研究方法》。 接着向量体系结构(2)讲&#xff0c;解决最后留下的问题中的两个问题 向量体系结构&#xff1a;向量执行时间-CSDN博客 &#xff08;1&#xff09;向量处理器如何实现每个时钟周期处理多于一个元素的能力? &#xff08;2&#x…

Hdfs小文件治理策略以及治理经验

小文件是 Hadoop 集群运维中的常见挑战&#xff0c;尤其对于大规模运行的集群来说可谓至关重要。如果处理不好&#xff0c;可能会导致许多并发症。Hadoop集群本质是为了TB,PB规模的数据存储和计算因运而生的。为啥大数据开发都说小文件的治理重要&#xff0c;说HDFS 存储小文件…

Echarts关系图的配置项,一文全解,一目了然。

一、什么是关系图 ECharts 是一个由百度开发的开源可视化库&#xff0c;用于创建丰富的交互式数据可视化图表。关系图&#xff08;Relationship Graph&#xff09;是 ECharts 中的一种图表类型&#xff0c;用于展示节点之间的关系和连接。 关系图通常用于展示复杂的网络结构&a…

2024年 Java 面试八股文——Mybatis篇

目录 1. 什么是Mybatis&#xff1f; 2. 说说Mybatis的优缺点 3. Xml映射文件中&#xff0c;都有哪些标签 4. #{}和&{}有什么区别 5. Mybatis是如何进行分页的,分页插件的原理是什么 6. Mybatis是如何将sql执行结果封装为目标对象并返回的&#xff1f; 7. Mybatis是怎…

vscode远程免密ssh原理与实操方法

什么是SSH SSH是一种加密协议&#xff0c;全称为Secure Shell&#xff0c;用于安全地远程登录到服务器或其他远程设备上执行命令或传输文件。它提供了一种安全的加密通信机制&#xff0c;使得远程登录和文件传输等操作不会被恶意攻击者窃取或篡改&#xff0c;确保了数据的保密…

5.3 进程间通信管道和共享内存

每次打开一个网页都是一个进程 进行管道之间通信的方式&#xff1a;以前学到的有可以在磁盘上开辟空间进行交互&#xff0c;也可以在内存中开辟缓冲区进行交互。 一定注意可读性 管道就是属于在内存中的一片缓冲区&#xff0c;管道可以在命令行中创建管道mkfifo也可以在vim中…

(优作)基于STM32蓝牙控制小车系统设计(硬件+源代码+论文)竞赛作品

基于STM32蓝牙控制小车系统设计&#xff08;硬件源代码论文&#xff09;竞赛作品 基于意法半导体与ARM公司生产的STM32F4 DISCOVERY开发板的集电机驱动模块、电源管理模块、stm32f4主控模块、蓝牙串口通信模块、android控制端模块。电机驱动模块使用了两个L298N芯片来驱动4路电…

基于SSM SpringBoot vue教务排课系统

基于SSM SpringBoot vue教务排课系统 系统功能 登录 个人中心 学生信息管理 教师信息管理 课室信息管理 班级信息管理 系别信息管理 专业信息管理 课程信息管理 选课信息管理 课表信息管理 开发环境和技术 开发语言&#xff1a;Java 使用框架: SSM(Spring SpringMVC Myba…

【Qt基础教程】QGridLayout与QFormLayout

文章目录 前言一、QGridLayout二、QFormLayout总结 前言 在Qt应用程序开发中&#xff0c;布局管理器是一种关键的技术&#xff0c;用于管理和安排窗口小部件的位置和大小。QGridLayout和QFormLayout是两个常用的布局管理器&#xff0c;它们分别适用于网格状和表单状的界面布局…

创新指南 | 围绕“获客、转化、增长”三要素,构建 PLG线上运营 体系

构建一个高效的 PLG线上运营 体系&#xff0c;对于任何希望利用产品本身优势推动业务增长的公司来说都是至关重要的。PLG模式通过产品本身的力量来驱动用户增长、促进转化并提升用户体验&#xff0c;从而实现自然而持续的增长。 一、PLG线上运营的整体框架和思路 PLG线上运营 …

百度网盘里的文件怎么打印?

在日常生活和工作中&#xff0c;我们经常需要打印各种文件&#xff0c;包括学习资料、工作报告、合同文件等。有时候&#xff0c;这些文件保存在百度网盘等云存储服务中&#xff0c;我们该如何方便地打印出来呢&#xff1f;今天&#xff0c;就为大家介绍一种便捷的方法——通过…

InfiniFlow 創始人兼CEO張穎峰確認出席“邊緣智能2024 - AI開發者峰會”

隨著AI技術的迅猛發展&#xff0c;全球正逐步進入邊緣計算智能化與分布式AI深度融合的新時代&#xff0c;共同書寫著分布式智能創新應用的壯麗篇章。邊緣智能&#xff0c;作為融合邊緣計算和智能技術的新興領域&#xff0c;正逐漸成為推動AI發展的關鍵力量。借助分布式和去中心…

[数据结构]———归并排序

具体代码&#xff1a;在gitee仓库&#xff1a;登录 - Gitee.com 目录 ​编辑 1.基本思想&#xff1a; 2. 代码解析 1.分析 2.逻辑图 3.运行结果 1.基本思想&#xff1a; 归并排序&#xff08;MERGE-SORT&#xff09;是建立在归并操作上的一种有效的排序算法,该算法是采用分…

7个策略,让你的可视化大屏打动人心!

要打动人心的可视化大屏&#xff0c;可以采取以下策略&#xff1a; 引人入目的设计&#xff1a; 选择鲜明而吸引人的颜色和视觉效果&#xff0c;使用引人注目的动画和过渡效果&#xff0c;以及吸引眼球的图形和图案设计。通过精心设计的布局和排版&#xff0c;确保信息清晰可…

leetcode_43.字符串相乘

43. 字符串相乘 题目描述&#xff1a;给定两个以字符串形式表示的非负整数 num1 和 num2&#xff0c;返回 num1 和 num2 的乘积&#xff0c;它们的乘积也表示为字符串形式。 注意&#xff1a;不能使用任何内置的 BigInteger 库或直接将输入转换为整数。 示例 1: 输入: num1 &q…

Static内存分析

title: Static内存分析 tags: Java基础知识 abbrlink: 49066 date: 2021-04-25 19:06:41 Static内存分析 一.基础须知 1.静态变量 1&#xff09;定义&#xff1a; 在一个Java类中&#xff0c;可以使用static关键字来修饰全员变量&#xff0c;该变量被称作静态变量 2&…

【linux】重定向

重定向 什么是重定向如何实现一个简单的重定向关于重定向的系统调用接口 注意&#xff1a;在看这篇博客之前&#xff0c;最好是要对文件在系统中是如何被打开的以及操作系统是如何管理文件有一个初步了解&#xff0c;如果不了解的话&#xff0c;可以看看这篇博客《初步认识文件…

苹果CEO对未来一代人工智能投资持乐观态度

尽管在动荡的第二季度&#xff0c;苹果的收入和iPhone销量有所下降&#xff0c;但其新兴的人工智能技术可能会带来急需的提振。 在5月2日的电话财报会议上&#xff0c;苹果公布季度收入为908亿美元&#xff0c;比去年下降4%。iPhone的收入也下降了10%&#xff0c;至460亿美元。…

无言:破局之道:顿悟+坚持——早读(逆天打工人爬取热门微信文章解读)

致无言 引言Python 代码第一篇 洞见 7年跟踪调查北京28个精英家庭&#xff1a;为什么顶尖大学孩子大多来自有钱家庭&#xff1f;第二篇 人民日报 来了&#xff01;新闻早班车要闻社会政策 结尾 控制你的情绪 否则它将控制你 在紧张的游戏中 控制情绪 避免冲动行为 是每个玩家的…

Linux中动态库的用法及优缺点?怎样制作动态库和静态库?

一、什么是gcc gcc的全称是GNU Compiler Collection&#xff0c;它是一个能够编译多种语言的编译器。最开始gcc是作为C语言的编译器&#xff08;GNU C Compiler&#xff09;&#xff0c;现在除了c语言&#xff0c;还支持C、java、Pascal等语言。gcc支持多种硬件平台. 在 Linux…