您的位置:首页 > 其它

初探GCD

2015-07-25 11:40 357 查看

UI相关

ui相关的任务需要使用主线程来运行。

import UIKit

class ViewController: UIViewController {

override func viewDidLoad() {
super.viewDidLoad()

dispatch_async(dispatch_get_main_queue(), {
print("Current thread = \(NSThread.currentThread())")
print("Main thread = \(NSThread.mainThread())")
})
print("hello")

}

}


主线程在异步执行时会把需要执行的任务放在主队列队尾。
此程序将闭包内的程序放在队列末尾先打印“hello”,打印结束后开始执行闭包。

import UIKit

class ViewController: UIViewController {

override func viewDidLoad() {
super.viewDidLoad()

dispatch_async(dispatch_get_main_queue(), {[weak self] in

let alertController = UIAlertController(title: "GCD",
message: "GCD is amazing!",
preferredStyle: .Alert)

alertController.addAction(UIAlertAction(title: "OK",
style: .Default,
handler: nil))

self!.presentViewController(alertController,
animated: true,
completion: nil)

})

}

}


UI无关

UI无关的任务通常使用并发队列异步执行,这样不会阻塞主线程。
若使用并发队列同步执行,则还是不会开启新线程,依旧会使用当前线程(主线程)来执行。

import UIKit

class ViewController: UIViewController {

func printFrom1To1000(){

for counter in 0..<1000{
print("Counter = \(counter) - Thread = \(NSThread.currentThread())")
}

}

override func viewDidLoad() {
super.viewDidLoad()

let queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0)
dispatch_sync(queue, printFrom1To1000)
dispatch_sync(queue, printFrom1To1000)

}

}


结果如下:



import UIKit

class ViewController: UIViewController {

override func viewDidAppear(animated: Bool) {
super.viewDidAppear(animated)

let queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0)
dispatch_async(queue, {[weak self] in

var image: UIImage?

dispatch_sync(queue, {
/* Download the image here */

/* Put your own URL here */
let urlAsString = "http://pic.nipic.com/2007-11-09/2007119122519868_2.jpg"

let url = NSURL(string: urlAsString)
let urlRequest = NSURLRequest(URL: url!)
var downloadError: NSError?

let imageData: NSData?
do {
imageData = try NSURLConnection.sendSynchronousRequest(urlRequest,
returningResponse: nil)
} catch let error as NSError {
downloadError = error
imageData = nil
} catch {
fatalError()
}

if let error = downloadError{
print("Error happened = \(error)")
} else if let imageData = imageData{

if imageData.length > 0{
image = UIImage(data: imageData)
/* Now we have the image */
} else {
print("No data could get downloaded from the URL")
}

}

})

dispatch_sync(dispatch_get_main_queue(), {
/* Show the image to the user here on the main queue */

if let theImage = image{
let imageView = UIImageView(frame: self!.view.bounds)
imageView.contentMode = .ScaleAspectFit
imageView.image = theImage
self!.view.addSubview(imageView)
}

})

})
}

}


这个例子使用并发队列异步执行,不会阻塞主线程。

效果如下:



import UIKit

class ViewController: UIViewController {

func fileLocation() -> String?{

/* Get the document folder(s) */
let folders = NSSearchPathForDirectoriesInDomains(.DocumentDirectory,
.UserDomainMask,
true) as [String]

/* Did we find anything? */
if folders.count == 0{
return nil
}

/* Get the first folder */
let documentsFolder = folders[0]

/* Append the filename to the end of the documents path */
return documentsFolder.stringByAppendingPathComponent("list.txt")

}

func hasFileAlreadyBeenCreated() -> Bool{
let fileManager = NSFileManager()
if let theLocation = fileLocation(){
return fileManager.fileExistsAtPath(theLocation)
}
return false
}

override func viewDidAppear(animated: Bool) {
super.viewDidAppear(animated)

let concurrentQueue =
dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0)

/* If we have not already saved an array of 10,000
random numbers to the disk before, generate these numbers now
and then save them to the disk in an array */
dispatch_async(concurrentQueue, {[weak self] in

let numberOfValuesRequired = 10000

if self!.hasFileAlreadyBeenCreated() == false{
dispatch_sync(concurrentQueue, {

var arrayOfRandomNumbers = [Int]()

for _ in 0..<numberOfValuesRequired{
let randomNumber = Int(arc4random())
arrayOfRandomNumbers.append(randomNumber)
}

/* Now let's write the array to disk */
let array = arrayOfRandomNumbers as NSArray
array.writeToFile(self!.fileLocation()!, atomically: true)

})
}

var randomNumbers: NSMutableArray?

/* Read the numbers from disk and sort them in an
ascending fashion */
dispatch_sync(concurrentQueue, {
/* If the file has now been created, we have to read it */
if self!.hasFileAlreadyBeenCreated(){
randomNumbers = NSMutableArray(
contentsOfFile: self!.fileLocation()!)

/* Now sort the numbers */
randomNumbers!.sortUsingComparator({
(obj1: AnyObject!, obj2: AnyObject!) -> NSComparisonResult in
let number1 = obj1 as! NSNumber
let number2 = obj2 as! NSNumber
return number1.compare(number2)
})
}
})

dispatch_async(dispatch_get_main_queue(), {
if let numbers = randomNumbers{

if numbers.count > 0{
/* Refresh the UI here using the numbers in the
randomNumbers array */
print("The sorted array was read back from disk = \(numbers)")
} else {
print("The numbers array is emtpy")
}

}
})

})

}

}


延时一段时间

import UIKit

class ViewController: UIViewController {

override func viewDidLoad() {
super.viewDidLoad()

let delayInSeconds = 2.0

let delayInNanoSeconds =
dispatch_time(DISPATCH_TIME_NOW,
Int64(delayInSeconds * Double(NSEC_PER_SEC)))

let concurrentQueue =
dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0)

dispatch_after(delayInNanoSeconds, concurrentQueue, {
print("hello")
})

}

}


延时2秒后并发队列异步执行打印语句。

只执行一次

import UIKit

class ViewController: UIViewController {

var token: dispatch_once_t = 0
var numberOfEntries = 0

func executedOnlyOnce(){
numberOfEntries++;
print("Executed \(numberOfEntries) time(s)")

}

override func viewDidLoad() {
super.viewDidLoad()

dispatch_once(&token, executedOnlyOnce)
dispatch_once(&token, executedOnlyOnce)

}

}


效果如下:



群组

import UIKit

class ViewController: UIViewController {

func reloadTableView(){
/* Reload the table view here */
print(__FUNCTION__)
}

func reloadScrollView(){
/* Do the work here */
print(__FUNCTION__)
}

func reloadImageView(){
/* Reload the image view here */
print(__FUNCTION__)
}

override func viewDidLoad() {
super.viewDidLoad()

let taskGroup =  dispatch_group_create()
let mainQueue =  dispatch_get_main_queue()

/* Reload the table view on the main queue */
dispatch_group_async(taskGroup, mainQueue, {[weak self] in
self!.reloadTableView()
});

/* Reload the scroll view on the main queue */
dispatch_group_async(taskGroup, mainQueue, {[weak self] in
self!.reloadScrollView()
});

/* Reload the image view on the main queue */
dispatch_group_async(taskGroup, mainQueue, {[weak self] in
self!.reloadImageView()
});

/* At the end when we are done, dispatch the following block */
dispatch_group_notify(taskGroup, mainQueue, {[weak self] in
/* Do some processing here */

let controller = UIAlertController(title: "Finished",
message: "All tasks are finished",
preferredStyle: .Alert)

controller.addAction(UIAlertAction(title: "OK",
style: .Default,
handler: nil))

self!.presentViewController(controller, animated: true, completion: nil)

});

}

}


当所有群组的任务执行完之后执行group_notify任务。

小结:

1.主队列和全局队列

主队列
<1>串行队列,一次只执行一个任务
<2>队列所有任务都是在主线程执行
<3>所有UI更新的任务都需要放在主队列由主线程执行

全局队列
<1>并发队列,一次执行多个任务
<2>队列内任务可以由主线程完成也可以由其他线程完成,看具体的同步或异步执行方式。(在主线程执行区域内进行全局队列同步执行,则还是由当前线程(主线程)来执行)

2.同步执行和异步执行

同步执行
1.由当前线程执行(除了主队列的任务,需要主线程执行)
2.阻塞当前线程,必须等闭包执行完毕后在执行下面的任务(主线程执行区域内进行主队列的同步执行会造成死锁)
(串行队列的线程在执行过程中,遇到给该串行队列增加同步任务都会造成死锁)

异步执行
1.将任务放到队列尾就立刻返回,不会阻塞当前线程
2.交给其他线程进行任务

主线程外执行下载任务后更新界面的一般模式即为:

全局队列异步执行任务{    //不会阻塞主线程
//task  完成后
主队列异步执行更新UI任务{}
}

其中的主队列异步执行任务 也可以换成主队列同步执行任务,区别就是是否会阻塞当前执行下载任务的某线程。
若为同步执行,下载线程会等到改UI更新任务结束后才继续运行,若为异步任务,则会直接向下运行。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: