NSThread####
(每个NSThread对象对应一个线程,真正的多线程)
-
使用NSObject类的方法performSelectorInBackground:withObject:来创建一个线程。
[Object performSelectorInBackground:@selector(doSomething:) withObject:nil];对应的在主线程上调用的方法的(更新UI必须回到主线程): [Object performSelectorOnMainThread:@selector(doSomething:) withObject:nil waitUntilDone:NO];
-
选择使用NSThread实现多线程。
NSThread创建主要有两种方式:1:[NSThread detachNewThreadSelector:@selector(doSomething:) toTarget:self withObject:nil]; 2:NSThread* myThread = [[NSThread alloc] initWithTarget:self selector:@selector(doSomething:) object:nil]; [myThread start]; 这两种方式的区别在于: 前一种调用就会立即创建一个线程并执行selector方法;第二种方式尽管alloc了一个新Thread, 但需要手动调用start方法来启动线程。这点与Java创建线程的方式相似。 第一种方式,与上述做法1使用NSObject的类方法performSelectorInBackground:withObject:是一样的; 第二种方式的可以在start真正创建线程之前对其进行设置,比如设置线程的优先级。
还有要注意的是在多个线程都在执行同一个方法的时候要使用线程锁NSLock
我们可以使用指令 @synchronized 来简化 NSLock的使用,这样我们就不必显示编写创建NSLock,加锁并解锁相关代码。
- (void)doSomeThing:(id)anObj{
@synchronized(anObj) {
// Everything between the braces is protected by the @synchronized directive.
}}
Grand Central Dispatch (GCD)####
The main queue:主队列,串行队列
main queue可以调用dispatch_get_main_queue()来获得。因为main queue是与主线程相关的,所以这是一个串行队列。
dispatch_async(dispatch_get_main_queue(), ^{ // something });Global queues: 全局队列,并发队列(后台执行)
进程中存在三个全局队列:高、中(默认)、低三个优先级队列(实际还有一个更低优先级为DISPATCH_QUEUE_PRIORITY_BACKGROUND)。可以调用dispatch_get_global_queue函数传入优先级来访问队列。
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ // something });
***需要注意的是,三个队列不代表三个线程,可能会有更多的线程。并发队列可以根据实际情况来自动产生合理的线程数,也可理解为dispatch队列实现了一个线程池的管理,对于程序逻辑是透明的。 ***
-
用户队列
用户队列 (GCD并不这样称呼这种队列, 但是没有一个特定的名字来形容这种队列,所以我们称其为用户队列) 是用函数 dispatch_queue_create创建的队列. 这些队列是串行的。dispatch_queue_t queue = dispatch_queue_create("com.dispatch.serial", DISPATCH_QUEUE_SERIAL); dispatch_async(queue, ^{ // something }); //生成一个串行队列,队列中的block按照先进先出(FIFO)的顺序去执行,实际上为单线程执行。第一个参数是队列的名称,在调试程序时会非常有用,所有尽量不要重名了。 dispatch_queue_t queue = dispatch_queue_create("com.dispatch.concurrent", DISPATCH_QUEUE_CONCURRENT); dispatch_async(queue, ^{ // something }); //生成一个并发执行队列,block被分发到多个线程去执行 例子:多线程写同一数据库,需要保持写入的顺序和每次写入的完整性,简单地利用串行队列即可实现: dispatch_queue_t queue1 = dispatch_queue_create("com.dispatch.writedb", DISPATCH_QUEUE_SERIAL); - (void)writeDB:(NSData *)data { dispatch_async(queue1, ^{ //write database }); } 下一次调用writeDB:必须等到上次调用完成后才能进行,保证writeDB:方法是线程安全的。