語(yǔ)言:Swift3.1
|| Object-C
(本文使用Swift3.1)
作用:提高效率掰烟,同時(shí)處理多個(gè)task。
工具:xcode8.3.2
系統(tǒng):MAC OX
iOS中的各種多線(xiàn)程
NSThread
每個(gè)NSThread
對(duì)象都是一個(gè)線(xiàn)程沐批。比較輕量級(jí)纫骑,無(wú)法做到復(fù)雜的操作。
初始化方式
1??普通實(shí)例化
let thread: Thread = Thread.init(target: self, selector: #selector(joinImage(imageURL:)), object: URL.init(string: "http://img02.tooopen.com/images/20140127/sy_54827852166.jpg"))
2??靜態(tài)方法實(shí)例化
Thread.detachNewThreadSelector(#selector(joinImage(imageURL:)), toTarget: self, with: URL.init(string: "http://img02.tooopen.com/images/20140127/sy_54827852166.jpg"))
3??隱式方法實(shí)例化
self.performSelector(inBackground: #selector(joinImage(imageURL:)), with: URL.init(string: "http://img02.tooopen.com/images/20140127/sy_54827852166.jpg"))
具體工程代碼如下:
class ViewController: UIViewController {
@IBOutlet weak var imageView: UIImageView!
override func viewDidLoad() {
super.viewDidLoad()
}
@IBAction func generalMethod(_ sender: Any) {
let thread: Thread = Thread.init(target: self, selector: #selector(joinImage(imageURL:)), object: URL.init(string: "http://img02.tooopen.com/images/20140127/sy_54827852166.jpg"))
thread.start()
}
@IBAction func staticMethod(_ sender: Any) {
Thread.detachNewThreadSelector(#selector(joinImage(imageURL:)), toTarget: self, with: URL.init(string: "http://img02.tooopen.com/images/20140127/sy_54827852166.jpg"))
}
@IBAction func ImplicitMethod(_ sender: Any) {
self.performSelector(inBackground: #selector(joinImage(imageURL:)), with: URL.init(string: "http://img02.tooopen.com/images/20140127/sy_54827852166.jpg"))
}
@objc private func joinImage(imageURL: URL) {
let data: Data = try!Data.init(contentsOf: imageURL)
let image: UIImage? = UIImage.init(data: data)
if let imageisOK = image {
self.performSelector(onMainThread: #selector (refreshUI(image:)), with: imageisOK, waitUntilDone: true)
} else {
print("圖片加載失斁藕ⅰO裙荨!L杀颉煤墙!")
}
}
@objc private func refreshUI(image: UIImage) {
imageView.image = image;
}
NSThread
還提供多種簡(jiǎn)單方法,詳細(xì)查看其API宪拥,不再介紹仿野。
NSOperation
需要結(jié)合NSOperationQueue
實(shí)現(xiàn)多線(xiàn)程編程。
初始化方式:
1??使用NSInvocationOperation
(由于swift中無(wú)此不安全的類(lèi)她君。所以次數(shù)直接上代碼)
NSInvocationOperation *invocationOperation = [[NSInvocationOperation alloc] initWithTarget:self selector:@selector(refreshUI:) object:imgUrl];
//[invocationOperation start];//會(huì)在主線(xiàn)程執(zhí)行
NSOperationQueue *queue = [[NSOperationQueue alloc]init];
[queue addOperation:invocationOperation];
2??使用BlockOperation
初始化
let blockOperation = BlockOperation.init {
self.joinImage(imageURL: URL.init(string: "http://img02.tooopen.com/images/20140127/sy_54827852166.jpg")!)
}
let operationQueue = OperationQueue.init()
operationQueue.addOperation(blockOperation)
3??自定義一個(gè)Operation的子類(lèi)實(shí)現(xiàn)
//創(chuàng)建一個(gè)自定義的類(lèi)繼承于Operation脚作,重寫(xiě)main方法,因?yàn)榫€(xiàn)程開(kāi)始會(huì)在內(nèi)部調(diào)用這個(gè)方法
@objc protocol loadImageProtocol {
}
class MyOperation: Operation {
var urlImage: URL = URL.init(string: "http://img02.tooopen.com/images/20140127/sy_54827852166.jpg")!
weak var deleagte: loadImageProtocol?
override func main() {
if self.isCancelled {
return
}
if let dele = deleagte {
let controller = dele as! ViewController
controller.joinImage(imageURL: urlImage)
}
}
}
使用如下:
//初始化自定義的類(lèi),并且指定代理最后加入隊(duì)列即可球涛。
let myOp: MyOperation = MyOperation.init()
myOp.deleagte = self
let operationQueue = OperationQueue.init()
operationQueue.addOperation(myOp)
GCD
同步 | 異步 | |
---|---|---|
串行隊(duì)列 | 在主線(xiàn)程劣针,任務(wù)一個(gè)個(gè)執(zhí)行,阻塞主線(xiàn)程 | 任務(wù)一個(gè)個(gè)執(zhí)行亿扁,不阻塞主線(xiàn)程 |
并行隊(duì)列 | 在主線(xiàn)程捺典,由于只有一個(gè)線(xiàn)程,所以一個(gè)個(gè)執(zhí)行魏烫,阻塞主線(xiàn)程 | 很多線(xiàn)程辣苏,并發(fā)執(zhí)行 |
創(chuàng)建隊(duì)列
在Swift3.0中對(duì)GCD進(jìn)行了封裝 使用DispatchQueue來(lái)進(jìn)行GCD的操作,OC中繼續(xù)使用dispatch_queue_xxxxx
類(lèi)似C的寫(xiě)法。
①主隊(duì)列(串行)(只用于刷新UI等操作)
let queue=DispatchQueue.main
②自定義一個(gè)隊(duì)列(可以為串行哄褒,可以為并行)
//最簡(jiǎn)單的初始化隊(duì)列方式稀蟋,為串行,優(yōu)先級(jí)默認(rèn),label為唯一標(biāo)識(shí)符呐赡。
let quque = DispatchQueue.init(label: "test.jp.Queue")
//為串行退客,優(yōu)先級(jí)utility,label為唯一標(biāo)識(shí)符。
let quque1=DispatchQueue.init(label: "test.jp.Queue", qos: .utility)
//為并行隊(duì)列链嘀,優(yōu)先級(jí)utility
let quque2=DispatchQueue.init(label: "", qos: .utility, attributes: .concurrent)
③全局并發(fā)隊(duì)列萌狂,默認(rèn)的全局并發(fā)隊(duì)列,一般并發(fā)都可以使用
let queue = DispatchQueue.global()
創(chuàng)建任務(wù)
①同步任務(wù)(很容易造成死鎖)
let quque = DispatchQueue.init(label: "test.jp.Queue")
quque.sync {
print("hanihao")
}
②異步任務(wù)
let quque1=DispatchQueue.init(label: "test.jp.Queue", qos: .utility)
quque1.async {
print("nihao!!!")
}
手動(dòng)觸發(fā)隊(duì)列(iOS 10.0以上)
var quque: DispatchQueue?
if #available(iOS 10.0, *) {
let quque = DispatchQueue.init(label: "com.jp.queue", qos: .default, attributes: [.concurrent, .initiallyInactive])
quque.async {
for i in 0...100 {
print("\(i)")
}
}
}
//開(kāi)始隊(duì)列
if #available(iOS 10.0, *) {
quque?.activate()
}
延遲執(zhí)行
quque.asyncAfter(deadline: .now() + 0.88, execute: {
for i in 0...100 {
print("\(i)")
}
})
使用DispatchWorkItem
DispatchWorkItem
是一個(gè)代碼塊怀泊,具體用法很簡(jiǎn)單茫藏,看下面代碼
let myqueue = DispatchQueue.init(label: "myqueue")
let workitem = DispatchWorkItem.init {
for _ in 0...100 {
print("DispatchWorkItem的使用!E怼务傲!")
}
}
myqueue.async(execute: workitem)
使用DispatchGroup
場(chǎng)景:在所有任務(wù)完成之后需要進(jìn)行某些操作時(shí)使用DispatchGroup
。
示例:
let group = DispatchGroup.init()
let queue = DispatchQueue.global()
queue.async(group: group) {
self.createImage(imageView: self.imageView1, url: URL.init(string: "http://img02.tooopen.com/images/20140127/sy_54827852166.jpg")!)
}
queue.async(group: group) {
self.createImage(imageView: self.imageView2, url: URL.init(string: "http://img02.tooopen.com/images/20140127/sy_54827852166.jpg")!)
}
// 不阻塞主線(xiàn)程
group.notify(queue: DispatchQueue.global()) {
print("全部加載完畢")
}
// 永久等待枣申,直到所有任務(wù)執(zhí)行結(jié)束售葡,中途不能取消,阻塞當(dāng)前線(xiàn)程(不推薦使用)
group.wait()
print("組中任務(wù)全部完畢V姨佟P铩!")
特別注意
①更新UI一樣要在主線(xiàn)程模孩。
②并發(fā)隊(duì)列和串行隊(duì)列的區(qū)別尖阔,本質(zhì)上即為線(xiàn)程數(shù)量的區(qū)別,串行隊(duì)列為在一個(gè)線(xiàn)程中序列執(zhí)行榨咐,并發(fā)隊(duì)列為在多個(gè)線(xiàn)程中一起執(zhí)行诺祸。
一些簡(jiǎn)單的示例代碼已經(jīng)上傳碼云
地址: swift多線(xiàn)程Demo
更多功能請(qǐng)查看詳細(xì)API。