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 } |
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 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被点击同时生效