iOS开发Swift篇(02) NSThread线程相关简单说明

简介: iOS开发Swift篇(02) NSThread线程相关简单说明 一 说明   1)关于多线程部分的理论知识和OC实现,在之前的博文中已经写明,所以这里不再说明。   2)该文仅仅简单讲解NSThread在swift语境中的一些使用和注意点,别他。

iOS开发Swift篇(02) NSThread线程相关简单说明

一 说明

  1)关于多线程部分的理论知识和OC实现,在之前的博文中已经写明,所以这里不再说明。

  2)该文仅仅简单讲解NSThread在swift语境中的一些使用和注意点,别他。

  3)本文涉及代码可以从https://github.com/HanGangAndHanMeimei/Code地址获得。

二 NSThread的基本使用和创建

  1)基本用法(主线程|当前线程)

 1        //1.获得执行该方法的当前线程
 2         let currentThread = NSThread.currentThread()
 3         print("当前线程为\(currentThread)")
 4 
 5         //2.获得应用程序的主线程
 6         let mainThread = NSThread.mainThread()
 7         print("应用程序的主线程\(mainThread)")
 8 
 9         //3.判断当前线程是否是主线程
10         let isMain =  NSThread.isMainThread() 

  2)创建线程

  说明:此处列出创建线程的四种方法:分别是

  直接创建|分离出一条子线程|创建一条后台线程|自定义线程类继承自NSThread重写内部的main方法封装任务,然后init创建。

 1 //NSThread创建线程的四种方式
 2     func createNewThreadWithNSThreadMethodOne()
 3     {
 4         //1.创建线程
 5         let thread = NSThread.init(target: self, selector:Selector("run"), object: nil)
 6 
 7         //设置线程的名称
 8         thread.name = "线程A"
 9 
10         //2.启动线程
11         thread.start()
12     }
13 
14     func createNewThreadWithNSThreadMethodTwo()
15     {
16         //分离出一条子线程,自动启动线程,但无法获得线程对象
17         NSThread.detachNewThreadSelector(Selector("run"), toTarget: self, withObject: nil)
18     }
19 
20     func createNewThreadWithNSThreadMethodThree()
21     {
22         //开启一条后台线程,自动启动线程,但无法获得线程对象
23         self.performSelectorInBackground(Selector("run"), withObject: nil);
24     }
25 
26     func createNewThreadWithNSThreadMethodFour()
27     {
28         //let thread =  CustomThread.init(target: self, selector:Selector("run"), object: nil)
29         let thread = CustomThread();
30         thread.start()
31     }
32 
33     func run()
34     {
35         //获得当前执行run方法的线程
36         let thread = NSThread.currentThread()
37         print("run--\(thread.name)-\(thread)");
38    }

三 NSThread线程的状态和线程安全

  1)线程的状态

    线程的状态:新建-就绪-运行-阻塞-死亡

1      //线程的退出
2         NSThread.exit()
3         //线程的休眠1
4         NSThread.sleepForTimeInterval(2.0)
5         //线程的休眠2
6         NSThread.sleepUntilDate(NSDate.init(timeIntervalSinceNow: 3.0))

  2)线程安全

    说明:多线程访问同一个资源的时候可能会出现数据错乱等安全问题,解决方法是对必要的代码段进行加锁。

    注意:在OC中加互斥锁使用@synchronized(self) {},在swift可以使用objc_sync_enter(self)和objc_sync_exit(self)方法,注意这两个方法必须成对使用,把要加锁的代码放在中间

 1 class ViewController: UIViewController {
 2 
 3     //设置总票数为100张
 4     var totalTickets = 100
 5 
 6     override func viewDidLoad() {
 7         super.viewDidLoad()
 8 
 9         //多线程访问资源加锁
10         //创建三条线程分别代表售票员A、售票员B、售票员C
11         let thread01 = NSThread.init(target: self, selector:Selector("saleTickect"), object: nil)
12         let thread02 = NSThread.init(target: self, selector: Selector("saleTickect"), object: nil);
13         let thread03 = NSThread.init(target: self, selector: Selector("saleTickect"), object: nil);
14 
15         //设置线程的名称
16         thread01.name = "售票员A"
17         thread02.name = "售票员B"
18         thread03.name = "售票员C"
19 
20         //开启线程
21         thread01.start()
22         thread02.start()
23         thread03.start()
24 
25     }
26 
27     //模拟售票的函数
28     func saleTickect()
29     {
30         while(true)
31         {
32             //加互斥锁
33             /*
34             * 1)同OC中的@synchronized(self) {}
35             * 2)objc_sync_enter(self)和objc_sync_exit(self)必须成对使用,把要加锁的代码放在中间
36             */
37 
38             objc_sync_enter(self)
39 
40             //检查是否有余票,如果有则卖出去一张
41             let temp = totalTickets
42             for var i=0;i<100000;i++
43             {
44                 //空的for循环,模拟延迟
45             }
46 
47             if(temp>0)
48             {
49                 totalTickets = temp - 1
50                 print("\(NSThread.currentThread().name)卖出去了一张票,还剩\(totalTickets)")
51             }else
52             {
53                 print("\(NSThread.currentThread().name)发现票已经卖完了")
54                 break;
55             }
56             
57             objc_sync_exit(self)
58         }
59         
60     }
61     
62 }
线程安全Code示例

三 NSThread线程间通信

  1)说明

    所谓线程间通信,即如何从一个线程进入到另一个线程继续执行任务或者是传递参数(如从子线程回到主线程)

    下面的代码示例演示在主线程中先创建一个子线程下载图片,当图片下载完成后又切换到主线程设置图片的操作。

 1 //!!!注意,该案例内部下载图片,发送了http请求需要修改info.plist文件
 2     class ViewController: UIViewController {
 3 
 4     @IBOutlet weak var imageView: UIImageView!
 5 
 6     override func viewDidLoad() {
 7         super.viewDidLoad()
 8 
 9         //程序启动后开子线程下载图片,图片下载完成之后回到主线程设置图片
10          NSThread.detachNewThreadSelector(Selector("downloadImage"), toTarget: self, withObject: nil)
11     }
12 
13     func downloadImage()
14     {
15         //1.获得要下载图片的url
16         let url = NSURL.init(string: "http://p9.qhimg.com/t014d1bd470cb60ac6e.jpg")
17 
18         //2.把url地址指向资源的二进制下载到本地
19         let imageData = NSData.init(contentsOfURL: url!)
20 
21         //3.把二进制数据转换为图片
22         let image = UIImage.init(data: imageData!);
23 
24         //4.打印查看当前线程(应该是在子线程中下载图片)
25         print("当前线程为\(NSThread.currentThread())")
26 
27         //5.线程间通信
28         //方法一
29         self.performSelectorOnMainThread(Selector("showImage:"), withObject: image, waitUntilDone:true)
30         //方法二
31         //imageView.performSelectorOnMainThread(Selector("setImage:"), withObject: image, waitUntilDone:true)
32     }
33 
34     
35     func showImage(image:UIImage)
36     {
37         //设置图片
38         imageView.image = image
39 
40         //打印查看设置图片操作的线程
41         print("处理UI刷新操作的线程\(NSThread.currentThread())")
42 
43     }
44 }
线程间通信示例Code

 

目录
相关文章
|
29天前
|
安全 Java 编译器
深入理解PHP 8.0新特性及其对开发的影响Java中的多线程编程:从理论到实践
【5月更文挑战第27天】在这篇文章中,我们将详细探讨PHP 8.0的新特性以及它们如何影响开发者的工作流程。我们将深入研究这些新特性,包括JIT编译器,联合类型,命名参数,以及更多的错误处理机制。我们还将讨论这些新特性如何提高代码的可读性和性能,以及它们如何改变我们编写和维护PHP应用程序的方式。 【5月更文挑战第27天】在现代计算机科学中,多线程编程是一个重要的概念,它允许多个线程在同一时间内运行,从而提高了程序的效率和性能。本文将深入探讨Java中的多线程编程,包括其理论基础,实现方法,以及一些常见的问题和解决方案。我们将通过实例来理解如何创建和管理线程,以及如何使用Java的并发工具来
|
6天前
|
存储 Swift 索引
Swift开发——索引器扩展
扩展用于向已存在的类型(例如,类、结构体、枚举和协议等)中添加新的功能,扩展甚至可以向系统类型(包括无法查阅代码的类型)中添加新的功能,但是扩展不能覆盖原类型中已有的方法,扩展也不能向类中添加新的存储属性。
27 6
Swift开发——索引器扩展
|
7天前
|
存储 Swift
Swift开发——属性检查器
Swift中的属性检查器(willSet, didSet)允许在设置存储属性值前后执行代码。在类`Circle`中,属性`radius`使用属性观察器:willSet在赋值前检查值,若值为负则打印警告;didSet在赋值后比较新旧值,根据变化输出相应信息。在实例`c`中,`radius`从-5变为0时,输出“Input value is negative.”和“The circle gets smaller.”;从0变为10时,输出“Input value is normal.”和“The circle gets larger.”。
11 4
Swift开发——属性检查器
|
9天前
|
Swift C++ 索引
Swift开发——简单函数实例
函数是编程的基础,用于封装特定功能的代码。它们有关键词func、函数名、参数列表(可为空)和返回类型。多返回值可通过元组、数组、inout参数或可选类型实现。例如,返回元组 `(value1, value2)`,数组 `[value1, value2]` 或使用可选数组 `[[Double]]?`。函数可以作为其他函数的参数,类似闭包或Lambda表达式。在Swift中,示例展示了通过元组、带索引的元组、数组和可选类型返回多个值的函数。还演示了如何使用inout参数交换变量值。
24 5
Swift开发——简单函数实例
|
6天前
|
存储 Swift
Swift开发——弱占用
Swift的自动引用计数(ARC)管理类实例内存,通过强引用保持实例存活。当出现强引用循环时,可使用`weak`关键字创建弱引用,避免阻止实例释放。弱引用在不再被强引用时导致对象立即释放。示例中,添加`weak`至`author`和`book`变量防止引用循环,使得两者析构器均执行,释放内存。图2展示了弱引用结构,当解除所有强引用后,ARC自动释放实例,调用析构器。
14 1
Swift开发——弱占用
|
7天前
|
存储 程序员 Swift
Swift开发——存储属性与计算属性
Swift推荐使用结构体进行开发,结构体支持属性和方法,且作为值类型。结构体属性包括存储属性(如radius)和计算属性(如r),计算属性不存储值,类似方法。结构体用`struct`定义,命名遵循大驼峰规则。实例名遵循小驼峰规则。属性可在结构体中任意位置定义,静态属性用`static`。存储属性可为`lazy`实现懒加载。结构体实例通过`.`访问属性和方法,静态属性和方法用`结构体名.`访问。计算属性可读写,可通过`get`和`set`定义。程序段1展示了结构体Point和Circle的属性和方法,包括私有属性、只读计算属性、可读写计算属性及`mutating`方法。
9 0
Swift开发——存储属性与计算属性
|
9天前
|
存储 算法 Swift
Swift开发——循环执行方式
Swift语言中的循环主要包括`for-in`和`while`结构。`for-in`适用于遍历数字区间、字符串和字典,支持使用`stride`函数定制步进。字典遍历时,可以用二元元组`(k, v)`访问键值对。`while`循环有标准形式和`repeat-while`形式,确保至少执行一次循环体。程序示例展示了`for-in`和不同`while`结构的用法,包括计算阶乘、奇数和、加密字符串以及最大公约数和最小公倍数。
13 0
Swift开发——循环执行方式
|
11天前
|
Swift 索引
Swift开发——元组
Swift中的元组是一种数据结构,用于组合不同类型的值。它们不是独立的数据类型,而是以有序序列形式存在,用圆括号括起,元素间用逗号分隔。元组可以有任意数量和类型的元素,可变性取决于其定义。常用于函数返回多个值。示例代码展示了元组的创建、访问、解包及赋值。元组可以通过标签来标识元素,支持嵌套和比较。在函数返回值和并行赋值场景中,元组特别有用。
23 0
Swift开发——元组
|
11天前
|
安全 JavaScript Swift
Swift开发——输出格式化字符
这篇文章介绍了Swift语言的基本概念和格式化输出方法。Swift是苹果平台的官方编程语言,强调类型安全,使用`main.swift`作为程序入口。文章通过示例展示了如何使用`print`函数进行格式化字符串输出,包括控制整数和浮点数的宽度、对齐方式以及使用`String(format:)`函数。示例代码创建了一个名为Ch0001的工程,并展示了不同输出方式,如常规输出、格式化输出和使用`\(`常量名或变量名`)`的形式。最后,文章给出了程序的运行结果截图。
20 0
Swift开发——输出格式化字符
|
28天前
|
JavaScript 前端开发 Swift
开发语言漫谈-Swift
wift就是个语言的大杂烩

相关课程

更多