iOS应用程序中通过dispatch队列控制线程执行的方法
GCD编程的核心就是dispatch队列,dispatchblock的执行最终都会放进某个队列中去进行,它类似NSOperationQueue但更复杂也更强大,并且可以嵌套使用。所以说,结合block实现的GCD,把函数闭包(Closure)的特性发挥得淋漓尽致。
dispatch队列的生成可以有这几种方式:
1.dispatch_queue_tqueue=dispatch_queue_create("com.dispatch.serial",DISPATCH_QUEUE_SERIAL);//生成一个串行队列,队列中的block按照先进先出(FIFO)的顺序去执行,实际上为单线程执行。第一个参数是队列的名称,在调试程序时会非常有用,所有尽量不要重名了。
2.dispatch_queue_tqueue=dispatch_queue_create("com.dispatch.concurrent",DISPATCH_QUEUE_CONCURRENT);//生成一个并发执行队列,block被分发到多个线程去执行
3.dispatch_queue_tqueue=dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT,0);//获得程序进程缺省产生的并发队列,可设定优先级来选择高、中、低三个优先级队列。由于是系统默认生成的,所以无法调用dispatch_resume()和dispatch_suspend()来控制执行继续或中断。需要注意的是,三个队列不代表三个线程,可能会有更多的线程。并发队列可以根据实际情况来自动产生合理的线程数,也可理解为dispatch队列实现了一个线程池的管理,对于程序逻辑是透明的。
官网文档解释说共有三个并发队列,但实际还有一个更低优先级的队列,设置优先级为DISPATCH_QUEUE_PRIORITY_BACKGROUND。Xcode调试时可以观察到正在使用的各个dispatch队列。
4.dispatch_queue_tqueue=dispatch_get_main_queue();//获得主线程的dispatch队列,实际是一个串行队列。同样无法控制主线程dispatch队列的执行继续或中断。
线程操作示例
为了方便地使用GCD,苹果提供了一些方法方便我们将block放在主线程或后台线程执行,或者延后执行。使用的例子如下所示:
// 后台执行: dispatch_async(dispatch_get_global_queue(0,0),^{ //something });
//主线程执行: dispatch_async(dispatch_get_main_queue(),^{ //something });
//一次性执行: staticdispatch_once_tonceToken; dispatch_once(&onceToken,^{ //codetobeexecutedonce });
//延迟2秒执行: doubledelayInSeconds=2.0; dispatch_time_tpopTime=dispatch_time(DISPATCH_TIME_NOW,delayInSeconds*NSEC_PER_SEC); dispatch_after(popTime,dispatch_get_main_queue(),^(void){ //codetobeexecutedonthemainqueueafterdelay });
dispatch_queue_t也可以自己定义,如要自定义queue,可以用dispatch_queue_create方法,示例如下:
//自定义dispatch_queue_t dispatch_queue_turls_queue=dispatch_queue_create("blog.devtang.com",NULL); dispatch_async(urls_queue,^{ //yourcode }); dispatch_release(urls_queue);
另外,GCD还有一些高级用法,例如让后台两个线程并行执行,然后等两个线程都结束后,再汇总执行结果。这个可以用dispatch_group_t、dispatch_group_async、dispatch_group_notify来实现,示例如下:
//合并汇总结果 dispatch_group_tgroup=dispatch_group_create(); dispatch_group_async(group,dispatch_get_global_queue(0,0),^{ //并行执行的线程一 }); dispatch_group_async(group,dispatch_get_global_queue(0,0),^{ //并行执行的线程二 }); dispatch_group_notify(group,dispatch_get_global_queue(0,0),^{ //汇总结果 });
dispatch队列不支持cancel(取消),没有实现dispatch_cancel()函数,不像NSOperationQueue,不得不说这是个小小的缺憾。