通常情况下,线程的优先级由内核自己管理,不过在OS X v10.6及以后的版本和iOS4到iOS7期间,NSOperation多了一个threadPriority属性,我们可以通过该属性设置Operation对象运行所在线程的优先级,数值范围为0.0到1.0,数字越高优先级越高。不过可能是出于线程安全等方面的考虑,Apple从iOS8开始废除了该属性。
OS X和iOS系统为我们提供了四种全局并发Dispatch Queue,所谓全局队列,就是我们不需要理会它们的保留和释放问题,而且不需要专门创建它。与其说是四种不如说是一种全局并发队列的四种不同优先级,因为它们之间唯一的不同之处就是队列优先级不同。与Operation Queue不同,在GCD中,Dispatch Queue只有四种优先级:
let highPriorityQueue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0) let defaultPriorityQueue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0)
如果需要验证或者测试当前队列,我们可以通过dispatch_get_current_queue函数获取当前队列。如果在闭包中调用,返回的是该闭包所在的队列,如果在闭包外调用,返回的则是默认的并发队列。不过该函数在OS X v10.10中和Swift中都不能使用了,取而代之的是通过DISPATCH_CURRENT_QUEUE_LABEL属性的get方法。
classTestDispatchQueue{ funclaunch() { let serialQueue = dispatch_queue_create("com.example.MySerialQueue", DISPATCH_QUEUE_SERIAL) dispatch_set_context(serialQueue, unsafeBitCast(0, UnsafeMutablePointer<Int>.self)) dispatch_async(serialQueue, { var taskCount = unsafeBitCast(dispatch_get_context(serialQueue), Int.self) taskCount++ print("TaskA in the dispatch queue...and The number of task in queue is \(taskCount)") dispatch_set_context(serialQueue, unsafeBitCast(taskCount, UnsafeMutablePointer<Int>.self)) sleep(1) }) dispatch_async(serialQueue, { var taskCount = unsafeBitCast(dispatch_get_context(serialQueue), Int.self) taskCount++ print("TaskB in the dispatch queue...and The number of task in queue is \(taskCount)") dispatch_set_context(serialQueue, unsafeBitCast(taskCount, UnsafeMutablePointer<Int>.self)) }) sleep(3) } }
let testDispatchQueue = TestDispatchQueue() testDispatchQueue.launch()
虽然在ARC时代,资源释放的工作已经基本不需要我们手动去做了,但有些时候因为系统释放资源并不是很及时,也会造成内存移除等问题,所以在一些情况下我们还是需要进行手动释放资源的工作,必入添加autoreleasepool保证资源及时释放等。Dispatch Queue也给我们提供了这样的机会(机会针对于ARC时代,在MRC时代是必须要做的),那就是Clean Up Function清理扫尾函数,当队列被释放时,或者说引用计数为0时会调用该函数,并且将上下文指针也传到了该函数,以便进行清理工作:
import Foundation
classContact: NSObject{ let name = "DevTalking" let mobile = "10010" }
classTestDispatchQueue{ let contact = Contact() functestCleanUpFunction() { launch() sleep(15) } funclaunch() { let serialQueue = dispatch_queue_create("com.example.MySerialQueue", DISPATCH_QUEUE_SERIAL)
dispatch_set_context(serialQueue, unsafeBitCast(contact, UnsafeMutablePointer<Void>.self)) dispatch_set_finalizer_f(serialQueue, myFinalizerFunction()) dispatch_async(serialQueue, { let contact = unsafeBitCast(dispatch_get_context(serialQueue), Contact.self) print("The name is \(contact.name)") sleep(1) }) dispatch_async(serialQueue, { let contact = unsafeBitCast(dispatch_get_context(serialQueue), Contact.self) print("The name is \(contact.mobile)") }) sleep(3) } funcmyFinalizerFunction() -> dispatch_function_t { return { context in let contact = unsafeBitCast(context, Contact.self) print("The name is \(contact.name) and the mobile is \(contact.mobile), The serialQueue has been released and we need clean up context data.") // TODO... } } }
let testDispatchQueue = TestDispatchQueue() testDispatchQueue.testCleanUpFunction()
其中一种实现任务异步执行的技术就是Grand Central Dispatch(GCD),该技术封提供了系统级别的线程管理功能,我们在使用它时只需要定义我们希望执行的任务,然后将任务添加到对应的分派执行队列中即可。另外一个技术是Operation queues,具体的实现是Objective-C中的NSOperationQueue对象,它的作用和GCD很相似,同样只需要我们定义好任务,然后添加到对应的操作队列中即可,其他与线程管理相关的事都由NSOperationQueue帮我们完成。
classTestBlockOperation{ funccreateBlockOperationObject() -> NSOperation { print("The main thread num is \(NSThread.currentThread())") let nsBlockOperation = NSBlockOperation(block: { print("Task in first closure. The thread num is \(NSThread.currentThread())") })
return nsBlockOperation } }
let testBlockOperation = TestBlockOperation()
let nsBlockOperation = testBlockOperation.createBlockOperationObject() nsBlockOperation.start()
The main thread id is <NSThread: 0x101502e40>{number = 1, name = main} Taskin first closure. The thread id is <NSThread: 0x101502e40>{number = 1, name = main}
classTestBlockOperation{ funccreateBlockOperationObject() -> NSOperation { print("The main thread num is \(NSThread.currentThread())") let nsBlockOperation = NSBlockOperation(block: { print("Task in first closure. The thread num is \(NSThread.currentThread())") }) // 第一种写法 nsBlockOperation.addExecutionBlock({ print("Task in second closure. The thread num is \(NSThread.currentThread())") }) // 第二种写法 nsBlockOperation.addExecutionBlock{ print("Task in third closure. The thread num is \(NSThread.currentThread())") }
return nsBlockOperation } }
let testBlockOperation = TestBlockOperation()
let nsBlockOperation = testBlockOperation.createBlockOperationObject() nsBlockOperation.start()
The main thread id is <NSThread: 0x101502e40>{number = 1, name = main} Taskin first closure. The thread id is <NSThread: 0x101502e40>{number = 1, name = main} Taskin third closure. The thread id is <NSThread: 0x101009190>{number = 2, name = (null)} Taskin second closure. The thread id is <NSThread: 0x101505110>{number = 3, name = (null)}
print(myConcurrentOperation.executing) print(myConcurrentOperation.finished) print(myConcurrentOperation.concurrent) sleep(10) } overridefuncobserveValueForKeyPath(keyPath: String?, ofObject object: AnyObject?, change: [String : AnyObject]?, context: UnsafeMutablePointer<Void>) { iflet change = change where context == &myContext { if keyPath == "finished" { print("Finish status has been changed, The new value is \(change[NSKeyValueChangeNewKey]!)") } elseif keyPath == "executing" { print("Executing status has been changed, The new value is \(change[NSKeyValueChangeNewKey]!)") } } } deinit { myConcurrentOperation.removeObserver(self, forKeyPath: "finished", context: &myContext) myConcurrentOperation.removeObserver(self, forKeyPath: "executing", context: &myContext) } }
funchandlePortMessage(message: NSPortMessage) { let messageId = message.msgid if messageId == UInt32(printMessageId) { print("Receive the message that id is 1000 and this is a print task.") } else { // Handle other messages } }
CAS操作是比较与交换(Compare and Swap)操作,有三个参数分别是旧值、新值、想要比较的值的内存地址,整个过程是先将你期望的旧值与指定的内存地址中的值进行比较,如果相同,那么将该内存地址的值更新为指定的新值,并返回true,如果比较后发现不同,那么不再做任何操作,并返回false,Apple提供了不同类型的CAS原子操作:
前文中说过,POSIX是可移植操作系统接口(Portable Operating System Interface of UNIX),它定义了操作系统应该为应用程序提供的接口标准,在类Unix系统中都可以使用。使用POSIX互斥锁很简单,先申明互斥锁指针,类型为UnsafeMutablePointer<pthread_mutex_t>,然后通过pthread_mutex_init函数初始化互斥锁,最后通过pthread_mutex_lock函数和pthread_mutex_unlock函数上锁和释放锁:
classTestLock{ let mutex: UnsafeMutablePointer<pthread_mutex_t> init() { mutex = UnsafeMutablePointer.alloc(sizeof(pthread_mutex_t)) }
// Begin synchronizing on 'obj'. // Allocates recursive mutex associated with 'obj' if needed. // Returns OBJC_SYNC_SUCCESS once lock is acquired. int objc_sync_enter(id obj) { int result = OBJC_SYNC_SUCCESS;
if (obj) { SyncData* data = id2data(obj, ACQUIRE); assert(data); data->mutex.lock(); } else { // @synchronized(nil) does nothing if (DebugNilSync) { _objc_inform("NIL SYNC DEBUG: @synchronized(nil); set a breakpoint on objc_sync_nil to debug"); } objc_sync_nil(); }
return result; }
// End synchronizing on 'obj'. // Returns OBJC_SYNC_SUCCESS or OBJC_SYNC_NOT_OWNING_THREAD_ERROR int objc_sync_exit(id obj) { int result = OBJC_SYNC_SUCCESS; if (obj) { SyncData* data = id2data(obj, RELEASE); if (!data) { result = OBJC_SYNC_NOT_OWNING_THREAD_ERROR; } else { bool okay = data->mutex.tryUnlock(); if (!okay) { result = OBJC_SYNC_NOT_OWNING_THREAD_ERROR; } } } else { // @synchronized(nil) does nothing }