swift开发多线程篇 - NSThread 线程相关简单说明(一些使用和注意点)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
一 说明
 
本文涉及代码可以从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 }
 
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 }

 

posted @   brave-sailor  阅读(268)  评论(0编辑  收藏  举报
编辑推荐:
· SQL Server 2025 AI相关能力初探
· Linux系列:如何用 C#调用 C方法造成内存泄露
· AI与.NET技术实操系列(二):开始使用ML.NET
· 记一次.NET内存居高不下排查解决与启示
· 探究高空视频全景AR技术的实现原理
阅读排行:
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· AI编程工具终极对决:字节Trae VS Cursor,谁才是开发者新宠?
· 开源Multi-agent AI智能体框架aevatar.ai,欢迎大家贡献代码
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
历史上的今天:
2016-02-22 eclipse项目迁移到android studio(图文最新版)
2016-02-22 ListView的Item被点击和其中的Button被点击同时生效
点击右上角即可分享
微信分享提示