GCD(Grand Central Dispatch)和Block 使用总结
2013-11-06 15:43
309 查看
今天在网上下载了一个小的Demo,就是一个“广告栏切换”效果。
代码的下载地址: http://123.th7.cn/code/jiandandeguanggaolan_749.html
其中有这么几段关键的代码:
-(void)AdImg:(NSArray*)arr{
[svsetContentSize:CGSizeMake(320*[arr
count], 189)];
page.numberOfPages=[arr
count];
for ( int i=0; i<[arr
count]; i++) {
NSString*url=[arr
objectAtIndex:i];
UIButton*img=[[UIButton
alloc]initWithFrame:CGRectMake(320*i,
0, 320,189)];
[imgaddTarget:self action:@selector(Action)
forControlEvents:UIControlEventTouchUpInside];
[svaddSubview:img];
UIImageFromURL( [NSURL
URLWithString:url], ^(UIImage * image)
{
[img
setImage:image forState:UIControlStateNormal];
},^(void){
});
}
}
#pragma mark -
下载图片
void UIImageFromURL(NSURL * URL,
void (^imageBlock)(UIImage * image),
void (^errorBlock)(void) )
{
dispatch_async( dispatch_get_global_queue(
DISPATCH_QUEUE_PRIORITY_DEFAULT,
0), ^(void)
{
NSData * data = [[NSData
alloc] initWithContentsOfURL:URL] ;
UIImage * image =[[UIImage
alloc] initWithData:data];
dispatch_async(
dispatch_get_main_queue(), ^(void){
if( image != nil )
{
imageBlock( image );
}
else {
errorBlock();
}
});
});
}
其实,代码中的知识点让我眼前一亮。于是,网上找资料,后来终于发现。代码所涉及的功能有两大块。
一、Grand Central Dispatch 简称(GCD)。
二、Block 的语法知识
那就开始吧。通过网上查资料,大概明白了中间的相关知识。更多的想把自己查到的、自己理解的贴上来,供大家学习,交流,指正。
Grand CentralDispatch 简称 (GCD)
GCD (Grand Central Dispatch)是Apple公司开发的一种技术,它旨在优化多核环境中的并发操作并取代传统多线程的编程模式。 在Mac OS X 10.7和IOS4.0之后开始支持GCD。
什么是GCD?
GCD-(Grand CentralDispatch)是Apple公司开发的一种技术。这种技术可以在多核硬件中并发处理多个任务。也可以说,GCD是多线程的一种扩展和替代技术。GCD在Mac OS x 10.6 和 IOS 4.0 以后开始支持。
可以来个更加专业的解释:
Grand Central Dispatch,或者简称 GCD,是一个与 BlockObject 产生工作的低级的 C API。GCD 真正的用途是将任务分配到多个核心又不让程序员担心哪个内核执行哪个任务。 在 MaxOS X 上,多内核设备,包括笔记本,用户已经使用了相当长的时间。通过多核设备 比如 iPad2 的介绍,程序员能为 iOS写出神奇的多核多线程
APP。
GCD 的核心是分派队列。不论在 iOS 还是 Max OS X分派队列,正如我们快看到的是 由位于主操作系统的 GCD 来管理的线程池。你不会直接与线程有工作关系。你只在分派队列上工作,将任务分派到这个队列上并要求队列来调用你的任务。GCD 为运行任务提供了几个选择:同步执行、异步执行和延迟执行等。
GCD有什么特点?或者说有什么优点?
1.GCD可以在充分利用多核硬件并发处理多个任务。也就是说,效率高。
2.GCD 的API提供了很多同步,异步,分组等正对多任务,同步,异步的操作。也就是一种比多线程还要牛X
写的技术。
3.使用GCD我们可以更容易的利用多核处理器并行处理任务。
4.GCD使用后不用程序去管理线程的开闭,GCD会在系统层面上去动态检测系统状态,开闭线程。
GCD API使用的相关方法
1.dispatch_get_global_queue方法
dispatch_get_global_queue(dispatch_queue_priority_tpriority,unsigned longflags);
得到一个当前的全局队列,根据指定的队列优先级。flags通常为0
dispatch_queue_t
globalQueue=dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT,
0);
dispatch_async 方法
dispatch_async(dispatch_queue_tqueue, dispatch_block_tblock);
在给定的调度队列中,异步执行相应的代码块。
dispatch_block_t代码块格式为:void(^dispatch_block_t)(void)
dispatch_get_main_queue() 方法
返回主队列。我们知道,更新UI只能在主队列中完成。所以,在涉及到更新UI的相关操作时,需要在主队列中进行。
dispatch_queue_create方法
dispatch_queue_t
queue = dispatch_queue_create("com.example.MyQueue",
NULL);
创建serialdispatch queue
dispatch queue采用FIFO的顺序执行块操作,但是在各个块执行过程中为并行执行。
dispatch queue
参数:1.字符串,2.给定的优先级,ios一般为空
dispatch_set_context方法
dispatch_set_context(queue,@"xxx");
为特定的dispatchqueue提供自定义的上下文信息(数据),注意:必须自己手动为该上下文信息(数据)分配和释放资源。
如果定义的上下文信息(数据)为空,那么dispatch_set_finalizer_f,指定的方法将不会被调用。
也就时说,当上下文信息(数据)为NULL时,myFinalizerFunction方法将不会被调用
dispatch_set_finalizer_f方法
dispatch_set_finalizer_f(queue,&myFinalizerFunction);
void myFinalizerFunction(){
NSLog(@"xxx");
// 该方法可以用来释放上下文信息(数据)
}
定义当dispatchqueue完成时,要调用的函数。
该函数可以完成一些release响应资源的操作。
dispatch_async方法
for (int i =
0; i<1000; i++) {
dispatch_async(queue, ^{
NSLog(@"%d",i);
});
}
让特定的dispatchqueue(queue)异步执行(指定的)块操作
dispatch_async、dispatch_async_f、dispatch_sync、dispatch_sync_f4个方法都可以用来为dispatch_queue(queue)添加任务
千万不要使用dispatch_sync或dispatch_sync_f将同一个dispatchqueue中正在执行的任务再次添加到这个queue中,如果这样做,会导致死锁。即:勿重复添加
dispatch_suspend方法和dispatch_resume方法
dispatch_suspend(queue);
dispatch_resume(queue);
dispatch_suspend会挂起dispatchqueue,但并不意味着当前正在执行的任务会停下来,
这只会导致不再继续执行还未执行的任务。dispatch_resume会唤醒已挂起的dispatchqueue。你必须确保它们成对调用。
dispatch_release方法
当dispatchqueue的引用计数达到0时,其所指定的清理函数就会被调用。
不应该对 global(main and concurrent) dispatch queues
调用该方法,
如果在global dispatch queues中调用该方法,不起作用
大致根据现在掌握的GCD的相关知识,已经能看懂以上相关GCD的代码片段。
当然,关于GCD还有很多的方法。有待学习啊!
Block 的语法知识
__block 声明的变量,是共享的。所以,以下输出中,队列中的输出值基本上都为1000,因为,异步执行中,i已经循环增长到1000,而 NSLog(@"%d",i)才输出。
dispatch_queue_t
aQueue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH,
0);
for (__block
int i = 0; i<1000; i++) {
dispatch_async(aQueue, ^{
NSLog(@"%d",i);
});
}
2012-12-29 20:40:57.630 DemoVideo[643:1c803] 15
2012-12-29 20:40:57.631 DemoVideo[643:1c803] 961
2012-12-29 20:40:57.631 DemoVideo[643:1c803] 1000
2012-12-29 20:40:57.631 DemoVideo[643:1c803] 1000
2012-12-29 20:40:57.631 DemoVideo[643:1c803] 1000
2012-12-29 20:40:57.631 DemoVideo[643:1c803] 1000
2012-12-29 20:40:57.631 DemoVideo[643:1c803] 1000
2012-12-29 20:40:57.632 DemoVideo[643:1ce03] 1000
2012-12-29 20:40:57.632 DemoVideo[643:1c803] 1000
2012-12-29 20:40:57.633 DemoVideo[643:1f00f] 1000
... ...
普通的变量,不是共享的,而是执行block语句块时的值。从输出可以看出。
dispatch_queue_t
aQueue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH,
0);
for (int i =
0; i<1000; i++) {
dispatch_async(aQueue, ^{
NSLog(@"%d",i);
});
}
2012-12-29 20:46:42.774 DemoVideo[669:1c803] 0
2012-12-29 20:46:42.774 DemoVideo[669:1c803] 1
2012-12-29 20:46:42.774 DemoVideo[669:1c803] 2
2012-12-29 20:46:42.774 DemoVideo[669:1c803] 3
2012-12-29 20:46:42.774 DemoVideo[669:1c803] 4
2012-12-29 20:46:42.775 DemoVideo[669:1c803] 5
2012-12-29 20:46:42.775 DemoVideo[669:1c803] 6
2012-12-29 20:46:42.776 DemoVideo[669:1c803] 9
2012-12-29 20:46:42.776 DemoVideo[669:1f303] 10
2012-12-29 20:46:42.777 DemoVideo[669:1c803] 11
... ...
Block也可以理解成匿名函数,或者再简单一些,就是可以当成一种特殊的数据类型,就像NSString和NSArray一样。Block有个好处,可以访问外部申明的变量。
希望对你有所帮助!
代码的下载地址: http://123.th7.cn/code/jiandandeguanggaolan_749.html
其中有这么几段关键的代码:
-(void)AdImg:(NSArray*)arr{
[svsetContentSize:CGSizeMake(320*[arr
count], 189)];
page.numberOfPages=[arr
count];
for ( int i=0; i<[arr
count]; i++) {
NSString*url=[arr
objectAtIndex:i];
UIButton*img=[[UIButton
alloc]initWithFrame:CGRectMake(320*i,
0, 320,189)];
[imgaddTarget:self action:@selector(Action)
forControlEvents:UIControlEventTouchUpInside];
[svaddSubview:img];
UIImageFromURL( [NSURL
URLWithString:url], ^(UIImage * image)
{
[img
setImage:image forState:UIControlStateNormal];
},^(void){
});
}
}
#pragma mark -
下载图片
void UIImageFromURL(NSURL * URL,
void (^imageBlock)(UIImage * image),
void (^errorBlock)(void) )
{
dispatch_async( dispatch_get_global_queue(
DISPATCH_QUEUE_PRIORITY_DEFAULT,
0), ^(void)
{
NSData * data = [[NSData
alloc] initWithContentsOfURL:URL] ;
UIImage * image =[[UIImage
alloc] initWithData:data];
dispatch_async(
dispatch_get_main_queue(), ^(void){
if( image != nil )
{
imageBlock( image );
}
else {
errorBlock();
}
});
});
}
其实,代码中的知识点让我眼前一亮。于是,网上找资料,后来终于发现。代码所涉及的功能有两大块。
一、Grand Central Dispatch 简称(GCD)。
二、Block 的语法知识
那就开始吧。通过网上查资料,大概明白了中间的相关知识。更多的想把自己查到的、自己理解的贴上来,供大家学习,交流,指正。
Grand CentralDispatch 简称 (GCD)
GCD (Grand Central Dispatch)是Apple公司开发的一种技术,它旨在优化多核环境中的并发操作并取代传统多线程的编程模式。 在Mac OS X 10.7和IOS4.0之后开始支持GCD。
什么是GCD?
GCD-(Grand CentralDispatch)是Apple公司开发的一种技术。这种技术可以在多核硬件中并发处理多个任务。也可以说,GCD是多线程的一种扩展和替代技术。GCD在Mac OS x 10.6 和 IOS 4.0 以后开始支持。
可以来个更加专业的解释:
Grand Central Dispatch,或者简称 GCD,是一个与 BlockObject 产生工作的低级的 C API。GCD 真正的用途是将任务分配到多个核心又不让程序员担心哪个内核执行哪个任务。 在 MaxOS X 上,多内核设备,包括笔记本,用户已经使用了相当长的时间。通过多核设备 比如 iPad2 的介绍,程序员能为 iOS写出神奇的多核多线程
APP。
GCD 的核心是分派队列。不论在 iOS 还是 Max OS X分派队列,正如我们快看到的是 由位于主操作系统的 GCD 来管理的线程池。你不会直接与线程有工作关系。你只在分派队列上工作,将任务分派到这个队列上并要求队列来调用你的任务。GCD 为运行任务提供了几个选择:同步执行、异步执行和延迟执行等。
GCD有什么特点?或者说有什么优点?
1.GCD可以在充分利用多核硬件并发处理多个任务。也就是说,效率高。
2.GCD 的API提供了很多同步,异步,分组等正对多任务,同步,异步的操作。也就是一种比多线程还要牛X
写的技术。
3.使用GCD我们可以更容易的利用多核处理器并行处理任务。
4.GCD使用后不用程序去管理线程的开闭,GCD会在系统层面上去动态检测系统状态,开闭线程。
GCD API使用的相关方法
1.dispatch_get_global_queue方法
dispatch_get_global_queue(dispatch_queue_priority_tpriority,unsigned longflags);
得到一个当前的全局队列,根据指定的队列优先级。flags通常为0
dispatch_queue_t
globalQueue=dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT,
0);
dispatch_async 方法
dispatch_async(dispatch_queue_tqueue, dispatch_block_tblock);
在给定的调度队列中,异步执行相应的代码块。
dispatch_block_t代码块格式为:void(^dispatch_block_t)(void)
dispatch_get_main_queue() 方法
返回主队列。我们知道,更新UI只能在主队列中完成。所以,在涉及到更新UI的相关操作时,需要在主队列中进行。
dispatch_queue_create方法
dispatch_queue_t
queue = dispatch_queue_create("com.example.MyQueue",
NULL);
创建serialdispatch queue
dispatch queue采用FIFO的顺序执行块操作,但是在各个块执行过程中为并行执行。
dispatch queue
参数:1.字符串,2.给定的优先级,ios一般为空
dispatch_set_context方法
dispatch_set_context(queue,@"xxx");
为特定的dispatchqueue提供自定义的上下文信息(数据),注意:必须自己手动为该上下文信息(数据)分配和释放资源。
如果定义的上下文信息(数据)为空,那么dispatch_set_finalizer_f,指定的方法将不会被调用。
也就时说,当上下文信息(数据)为NULL时,myFinalizerFunction方法将不会被调用
dispatch_set_finalizer_f方法
dispatch_set_finalizer_f(queue,&myFinalizerFunction);
void myFinalizerFunction(){
NSLog(@"xxx");
// 该方法可以用来释放上下文信息(数据)
}
定义当dispatchqueue完成时,要调用的函数。
该函数可以完成一些release响应资源的操作。
dispatch_async方法
for (int i =
0; i<1000; i++) {
dispatch_async(queue, ^{
NSLog(@"%d",i);
});
}
让特定的dispatchqueue(queue)异步执行(指定的)块操作
dispatch_async、dispatch_async_f、dispatch_sync、dispatch_sync_f4个方法都可以用来为dispatch_queue(queue)添加任务
千万不要使用dispatch_sync或dispatch_sync_f将同一个dispatchqueue中正在执行的任务再次添加到这个queue中,如果这样做,会导致死锁。即:勿重复添加
dispatch_suspend方法和dispatch_resume方法
dispatch_suspend(queue);
dispatch_resume(queue);
dispatch_suspend会挂起dispatchqueue,但并不意味着当前正在执行的任务会停下来,
这只会导致不再继续执行还未执行的任务。dispatch_resume会唤醒已挂起的dispatchqueue。你必须确保它们成对调用。
dispatch_release方法
当dispatchqueue的引用计数达到0时,其所指定的清理函数就会被调用。
不应该对 global(main and concurrent) dispatch queues
调用该方法,
如果在global dispatch queues中调用该方法,不起作用
大致根据现在掌握的GCD的相关知识,已经能看懂以上相关GCD的代码片段。
当然,关于GCD还有很多的方法。有待学习啊!
Block 的语法知识
__block 声明的变量,是共享的。所以,以下输出中,队列中的输出值基本上都为1000,因为,异步执行中,i已经循环增长到1000,而 NSLog(@"%d",i)才输出。
dispatch_queue_t
aQueue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH,
0);
for (__block
int i = 0; i<1000; i++) {
dispatch_async(aQueue, ^{
NSLog(@"%d",i);
});
}
2012-12-29 20:40:57.630 DemoVideo[643:1c803] 15
2012-12-29 20:40:57.631 DemoVideo[643:1c803] 961
2012-12-29 20:40:57.631 DemoVideo[643:1c803] 1000
2012-12-29 20:40:57.631 DemoVideo[643:1c803] 1000
2012-12-29 20:40:57.631 DemoVideo[643:1c803] 1000
2012-12-29 20:40:57.631 DemoVideo[643:1c803] 1000
2012-12-29 20:40:57.631 DemoVideo[643:1c803] 1000
2012-12-29 20:40:57.632 DemoVideo[643:1ce03] 1000
2012-12-29 20:40:57.632 DemoVideo[643:1c803] 1000
2012-12-29 20:40:57.633 DemoVideo[643:1f00f] 1000
... ...
普通的变量,不是共享的,而是执行block语句块时的值。从输出可以看出。
dispatch_queue_t
aQueue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH,
0);
for (int i =
0; i<1000; i++) {
dispatch_async(aQueue, ^{
NSLog(@"%d",i);
});
}
2012-12-29 20:46:42.774 DemoVideo[669:1c803] 0
2012-12-29 20:46:42.774 DemoVideo[669:1c803] 1
2012-12-29 20:46:42.774 DemoVideo[669:1c803] 2
2012-12-29 20:46:42.774 DemoVideo[669:1c803] 3
2012-12-29 20:46:42.774 DemoVideo[669:1c803] 4
2012-12-29 20:46:42.775 DemoVideo[669:1c803] 5
2012-12-29 20:46:42.775 DemoVideo[669:1c803] 6
2012-12-29 20:46:42.776 DemoVideo[669:1c803] 9
2012-12-29 20:46:42.776 DemoVideo[669:1f303] 10
2012-12-29 20:46:42.777 DemoVideo[669:1c803] 11
... ...
Block也可以理解成匿名函数,或者再简单一些,就是可以当成一种特殊的数据类型,就像NSString和NSArray一样。Block有个好处,可以访问外部申明的变量。
希望对你有所帮助!
相关文章推荐
- GCD(Grand Central Dispatch)和Block 使用-浅析
- GCD(Grand Central Dispatch)和Block 使用-浅析
- iOS GCD集汇(一)GCD(Grand Central Dispatch)和Block 使用-浅析
- GCD(Grand Central Dispatch)和Block 使用-浅析
- GCD(Grand Central Dispatch)和Block 使用-浅析
- GCD(Grand Central Dispatch)和Block 使用-浅析
- iOS GCD集汇(一)GCD(Grand Central Dispatch)和Block 使用-浅析
- 聊聊iOS下block + GCD (Grand Central Dispatch)实现异步非阻塞
- GCD(Grand Central Dispatch)和Block 使用-浅析 (2
- iOS线程开发之--BLOCK & GCD(Grand Central Dispatch)
- 聊聊iOS下block + GCD (Grand Central Dispatch)实现异步非阻塞
- 聊聊iOS下block + GCD (Grand Central Dispatch)实现异步非阻塞
- GCD(Grand Central Dispatch)的使用方法
- iOS GCD(Grand Central Dispatch)的使用(1)
- iOS线程开发之--BLOCK & GCD(Grand Central Dispatch)
- GCD的使用总结
- GCD(Grand Central Dispatch)
- iOS开发之GCD使用总结
- iOS开发之GCD使用总结
- iOS开发--多线程编程(四)GCD(Grand Central Dispatch)