ios 如何使用gcd,block

http://blog.sina.com.cn/s/blog_45e2b66c01010dhd.html

1。GCD之dispatch queue

http://www.cnblogs.com/scorpiozj/archive/2011/07/25/2116459.html

2。iOS中GCD的魔力

http://blog.csdn.net/favormm/article/details/6453260

3。官方 ,内容真的很多

http://developer.apple.com/library/ios/#documentation/Performance/Reference/GCD_libdispatch_Ref/Reference/reference.html

http://developer.apple.com/library/ios/#documentation/General/Conceptual/ConcurrencyProgrammingGuide/OperationQueues/OperationQueues.html#//apple_ref/doc/uid/TP40008091-CH102-SW1

4.详解IOS开发应用之并发Dispatch Queues

http://mobile.51cto.com/iphone-283323.htm

5。斯坦福大学关于gcd的讲义

http://www.stanford.edu/class/cs193p/cgi-bin/drupal/system/files/lectures/Lecture 13_0.pdf

gcd其实就是牛逼简化版的多线程。gcd和block是亲兄弟,所以学习gcd前需要了解block,不知道也没事,看看代码就明白了。

ios种GCD

GCD是和block紧密相连的,所以最好先了解下block(可以看我之前收藏的一篇文章).GCD是C level的函数,这意味着它也提供了C的函数指针作为参数,方便了C程序员.

下面首先来看GCD的使用:

dispatch_async(dispatch_queue_t queue, dispatch_block_t block);

async表明异步运行,block代表的是你要做的事情,queue则是你把任务交给谁来处理了.(除了async,还有sync,delay,本文以async为例).

之所以程序中会用到多线程是因为程序往往会需要读取数据,然后更新UI.为了良好的用户体验,读取数据的操作会倾向于在后台运行,这样以避免阻塞主线程.GCD里就有三种queue来处理.

1. Main queue:

  顾名思义,运行在主线程,由dispatch_get_main_queue获得.和ui相关的就要使用Main Queue.

2.Serial quque(private dispatch queue,其中dispatch_queue_t就是一种)

 每次运行一个任务,可以添加多个,执行次序FIFO. 通常是指程序员生成的,比如:

NSDate *da = [NSDate date]; NSString *daStr = [da description];

const char *queueName = [daStr UTF8String];
 dispatch_queue_t myQueue = dispatch_queue_create(queueName, NULL);

3. Concurrent queue(global dispatch queue,其中dispatch_time_t就是一种):

可以同时运行多个任务,每个任务的启动时间是按照加入queue的顺序,结束的顺序依赖各自的任务.使用dispatch_get_global_queue获得.

所以我们可以大致了解使用GCD的框架:

dispatch_async(getDataQueue,^{ //获取数据,获得一组后,刷新UI. dispatch_aysnc (mainQueue,^{ //UI的更新需在主线程中进行 }; } )

iosblocks是对象,它封装了一段代码,这段代码可以在任何时候执行。Blocks可以作为函数参数或者函数的返回值,而其本身又可以带输入参数或返回值。它和传统的函数指针很类似,但是有区别:blocksinline的,并且它对局部变量是只读的。

Ios4已经直接支持blocks

Blocks的定义:

         int (^Multiply)(int, int) = ^(int num1, int num2) {return num1 * num2;};

定义了一个Multiplyblocks对象,它带有两个int参数,返回int。等式右边就是blocks的具体实现,注意{}blocks体里的;。

Blocks可以访问局部变量,但是不能修改。

              int multiplier = 7;

     int (^myBlock)(int) = ^(int num) {

         multiplier ++;//编译报错

         return num * multiplier;

     };

如果要修改就要加关键字:__block

         __block int multiplier = 7;

     int (^myBlock)(int) = ^(int num) {

         multiplier ++;//这样就可以了

         return num * multiplier;

     };

作为函数的参数,blocks某种意义上替代了回调函数或者delegate。当函数调用了,假设某个事件触发,这时blocks里的内容就会运行。这样有利于代码的整合和阅读,你不需要到处去实现委托方法了。

系统API中已经有很多支持blocks参数了

·       Completion handlers

·       Notification handlers

·       Error handlers

·       Enumeration

·       View animation and transitions

·       Sorting


函数原型

dispatch_async(dispatch_queue_t queue, dispatch_block_t block);

async表明异步运行,.(除了async,还有sync,delay,本文以async为例).

queue则是你把任务交给谁来处理了

block代表的是你要做的事情

queue有三种

Main: tasks execute serially on your application’s main thread Concurrent: tasks start executing in FIFO order, but can run concurrently. Serial: tasks execute one at a time in FIFO order

  • (1)serial queues(串行队列)又称私有调度队列(private),一般用再对特定资源的同步访问上。我们可以根据需要创建任意数量的串行队列,每一个串行队列之间是并发的。
  • (2)并行队列,又称global dispatch queue。并行队列虽然可以并发的执行多个任务,但是任务开始执行的顺序和其加入队列的顺序相同。我们自己不能去创建并行调度队列。只有三个可用的global concurrent queues。
  • (3)main dispatch queue 是一个全局可用的串行队列,其在行用程序的主线程上执行任务。此队列的任务和应用程序的主循环(run loop)要执行的事件源交替执行。因为其运行在应用程序的主线程,main queue经常用来作为应用程序的一个同步点

先看一段代码

view plain

  1. @interface UIImageView (DispatchLoad)   
  2. - (void) setImageFromUrl:(NSString*)urlString;   
  3. - (void) setImageFromUrl:(NSString*)urlString    
  4.               completion:(void (^)(void))completion;   
  5. @end

view plain

  1. #import "UIImageView+DispatchLoad.h"   
  2. @implementation UIImageView (DispatchLoad)   
  3. - (void) setImageFromUrl:(NSString*)urlString {   
  4.     [self setImageFromUrl:urlString completion:NULL];   
  5. }   
  6. - (void) setImageFromUrl:(NSString*)urlString    
  7.               completion:(void (^)(void))completion {   
  8.        
  9.     dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{   
  10.            
  11.         NSLog(@"Starting: %@", urlString);   
  12.         UIImage *avatarImage = nil;    
  13.         NSURL *url = [NSURL URLWithString:urlString];   
  14.         NSData *responseData = [NSData dataWithContentsOfURL:url];   
  15.         avatarImage = [UIImage imageWithData:responseData];   
  16.         NSLog(@"Finishing: %@", urlString);   
  17.            
  18.         if (avatarImage) {   
  19.             dispatch_async(dispatch_get_main_queue(), ^{   
  20.                 self.image = avatarImage;   
  21.             });   
  22.             dispatch_async(dispatch_get_main_queue(), completion);   
  23.         }   
  24.         else {   
  25.             NSLog(@"-- impossible download: %@", urlString);   
  26.         }   
  27.     });      
  28. }   
  29. @end

以上代码主要是实现,图像异步加载。

分解一下:

1>添加到gcd队列

view plain

  1. dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{

这个代码主要实现,将图像加载block添加到queue队列中,

view plain

  1. dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0),

这个是获取全局并行队列(global dispatch queue),系统队列,只有3个。

2>加载图像。这个滤过

3>通知或更新主线程

view plain

  1. dispatch_async(dispatch_get_main_queue(), ^{   
  2.                 self.image = avatarImage;   
  3.             });   
  4.             dispatch_async(dispatch_get_main_queue(), completion);

“block的一个优势是可以使用其自己作用域外的变量,例如,一个block可以读取其父作用域的变量值,此值是copy到了block heap的数据结构中。当block被加入到dispatch queue中,这些值通常为只读形式。”

而更新UI只能在主线程中实现,所以调用主线程函数 completion

这样就完成了异步加载图像的流程。

当想要任务按照某一个特定的顺序执行时,串行队列是很有用的。串行队列在同一个时间只执行一个任务。我们可以使用串行队列代替锁去保护共享的数据。和锁不同,一个串行队列可以保证任务在一个可预知的顺序下执行。

和并发队列不同,我们要自己去创建和管理串行队列,可以创建任意数量的串行队列。当我们创建串行队列时,应出于某种目的,如保护资源,或者同步应用程序的某些关键行为。

下面的代码表述了怎么创建一个自定义的串行队列,函数dispath_queue_create需要两个参数,队列的名字,队列的属性。调试器和性能工具显示队列的名字帮助我们去跟踪任务是如何执行,队列的属性被保留供将来使用,应该为NULL

  1. dispatch_queue_t queue; 
  2. queue = dispatch_queue_create("com.example.MyQueue", NULL);

除了自己创建的自定义队列,系统会自动的给我创建一个串行队列并和应用程序的主线程绑定到一起。下面讲述如何获得它。

贴几段斯坦福大学关于gcd的代码,这段代码逐步演示了如何修正错误,其中用到的既是串行队列

1。这个是原始代码

view plain

  1. - (void)viewWillAppear:(BOOL)animated 
  2.     NSData *imageData = [FlickrFetcher imageDataForPhotoWithURLString:photo.URL]; 
  3.     UIImage *image = [UIImage imageWithData:imageData]; 
  4.     self.imageView.image = image; 
  5.     self.imageView.frame = CGRectMake(0, 0, image.size.width, image.size.height); 
  6.     self.scrollView.contentSize = image.size; 

2。这个是采用gcdd的代码,里面有错误3处

view plain

  1. - (void)viewWillAppear:(BOOL)animated 
  2.     dispatch_queue_t downloadQueue = dispatch_queue_create(“Flickr downloader”, NULL); 
  3.     dispatch_async(downloadQueue, ^{ 
  4.          NSData *imageData = [FlickrFetcher imageDataForPhotoWithURLString:photo.URL]; 
  5.          UIImage *image = [UIImage imageWithData:imageData]; 
  6.          self.imageView.image = image; 
  7.          self.imageView.frame = CGRectMake(0, 0, image.size.width, image.size.height); 
  8.          self.scrollView.contentSize = image.size; 
  9.     }); 

3。第一个错误,UI更新只能在主线程中 Problem! UIKit calls can only happen in the main thread!

改正后如下:

view plain

  1. - (void)viewWillAppear:(BOOL)animated 
  2.     dispatch_queue_t downloadQueue = dispatch_queue_create(“Flickr downloader”, NULL); 
  3.     dispatch_async(downloadQueue, ^{ 
  4.          NSData *imageData = [FlickrFetcher imageDataForPhotoWithURLString:photo.URL]; 
  5.         dispatch_async(dispatch_get_main_queue(), ^{
  6.              UIImage *image = [UIImage imageWithData:imageData]; 
  7.              self.imageView.image = image; 
  8.              self.imageView.frame = CGRectMake(0, 0, image.size.width, image.size.height); 
  9.              self.scrollView.contentSize = image.size; 
  10.          }); 
  11. }); } 

4。第二个错误,NSManagedObjectContext并不是线程安全的,gcd中访问成员变量有危险

Problem! NSManagedObjectContext is not thread safe,

so we can’t call photo.URL in downloadQueue’s t

改正后如下:

view plain

  1. - (void)viewWillAppear:(BOOL)animated 
  2.   NSString *url = photo.URL;
  3.     dispatch_queue_t downloadQueue = dispatch_queue_create(“Flickr downloader”, NULL); 
  4.     dispatch_async(downloadQueue, ^{ 
  5.         NSData *imageData = [FlickrFetcher imageDataForPhotoWithURLString:url];
  6.         dispatch_async(dispatch_get_main_queue(), ^{ 
  7.             UIImage *image = [UIImage imageWithData:imageData]; 
  8.             self.imageView.image = image; 
  9.             self.imageView.frame = CGRectMake(0, 0, image.size.width, image.size.height); 
  10.             self.scrollView.contentSize = image.size; 
  11. }); }); 

5。第三个错误,队列创建后没有释放,内存泄露

view plain

  1. - (void)viewWillAppear:(BOOL)animated 
  2.     NSString *url = photo.URL; 
  3.     dispatch_queue_t downloadQueue = dispatch_queue_create(“Flickr downloader”, NULL); 
  4.     dispatch_async(downloadQueue, ^{ 
  5.         NSData *imageData = [FlickrFetcher imageDataForPhotoWithURLString:url]; 
  6.         dispatch_async(dispatch_get_main_queue(), ^{ 
  7.             UIImage *image = [UIImage imageWithData:imageData]; 
  8.             self.imageView.image = image; 
  9.             self.imageView.frame = CGRectMake(0, 0, image.size.width, image.size.height); 
  10.             self.scrollView.contentSize = image.size; 
  11. }); }); 
  12.    dispatch_release(downloadQueue); //won’t actually go away until queue is empty }
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
VR(Virtual Reality)即虚拟现实,是一种可以创建和体验虚拟世界的计算机技术。它利用计算机生成一种模拟环境,是一种多源信息融合的、交互式的三维动态视景和实体行为的系统仿真,使用户沉浸到该环境中。VR技术通过模拟人的视觉、听觉、触觉等感觉器官功能,使人能够沉浸在计算机生成的虚拟境界中,并能够通过语言、手势等自然的方式与之进行实时交互,创建了一种适人化的多维信息空间。 VR技术具有以下主要特点: 沉浸感:用户感到作为主角存在于模拟环境中的真实程度。理想的模拟环境应该使用户难以分辨真假,使用户全身心地投入到计算机创建的三维虚拟环境中,该环境中的一切看上去是真的,听上去是真的,动起来是真的,甚至闻起来、尝起来等一切感觉都是真的,如同在现实世界中的感觉一样。 交互性:用户对模拟环境内物体的可操作程度和从环境得到反馈的自然程度(包括实时性)。例如,用户可以用手去直接抓取模拟环境中虚拟的物体,这时手有握着东西的感觉,并可以感觉物体的重量,视野中被抓的物体也能立刻随着手的移动而移动。 构想性:也称想象性,指用户沉浸在多维信息空间中,依靠自己的感知和认知能力获取知识,发挥主观能动性,寻求解答,形成新的概念。此概念不仅是指观念上或语言上的创意,而且可以是指对某些客观存在事物的创造性设想和安排。 VR技术可以应用于各个领域,如游戏、娱乐、教育、医疗、军事、房地产、工业仿真等。随着VR技术的不断发展,它正在改变人们的生活和工作方式,为人们带来全新的体验。
VR(Virtual Reality)即虚拟现实,是一种可以创建和体验虚拟世界的计算机技术。它利用计算机生成一种模拟环境,是一种多源信息融合的、交互式的三维动态视景和实体行为的系统仿真,使用户沉浸到该环境中。VR技术通过模拟人的视觉、听觉、触觉等感觉器官功能,使人能够沉浸在计算机生成的虚拟境界中,并能够通过语言、手势等自然的方式与之进行实时交互,创建了一种适人化的多维信息空间。 VR技术具有以下主要特点: 沉浸感:用户感到作为主角存在于模拟环境中的真实程度。理想的模拟环境应该使用户难以分辨真假,使用户全身心地投入到计算机创建的三维虚拟环境中,该环境中的一切看上去是真的,听上去是真的,动起来是真的,甚至闻起来、尝起来等一切感觉都是真的,如同在现实世界中的感觉一样。 交互性:用户对模拟环境内物体的可操作程度和从环境得到反馈的自然程度(包括实时性)。例如,用户可以用手去直接抓取模拟环境中虚拟的物体,这时手有握着东西的感觉,并可以感觉物体的重量,视野中被抓的物体也能立刻随着手的移动而移动。 构想性:也称想象性,指用户沉浸在多维信息空间中,依靠自己的感知和认知能力获取知识,发挥主观能动性,寻求解答,形成新的概念。此概念不仅是指观念上或语言上的创意,而且可以是指对某些客观存在事物的创造性设想和安排。 VR技术可以应用于各个领域,如游戏、娱乐、教育、医疗、军事、房地产、工业仿真等。随着VR技术的不断发展,它正在改变人们的生活和工作方式,为人们带来全新的体验。
基于GPT-SoVITS的视频剪辑快捷配音工具 GPT, 通常指的是“Generative Pre-trained Transformer”(生成式预训练转换器),是一个在自然语言处理(NLP)领域非常流行的深度学习模型架构。GPT模型由OpenAI公司开发,并在多个NLP任务上取得了显著的性能提升。 GPT模型的核心是一个多层Transformer解码器结构,它通过在海量的文本数据上进行预训练来学习语言的规律。这种预训练方式使得GPT模型能够捕捉到丰富的上下文信息,并生成流畅、自然的文本。 GPT模型的训练过程可以分为两个阶段: 预训练阶段:在这个阶段,模型会接触到大量的文本数据,并通过无监督学习的方式学习语言的结构和规律。具体来说,模型会尝试预测文本序列中的下一个词或短语,从而学习到语言的语法、语义和上下文信息。 微调阶段(也称为下游任务训练):在预训练完成后,模型会被应用到具体的NLP任务中,如文本分类、机器翻译、问答系统等。在这个阶段,模型会使用有标签的数据进行微调,以适应特定任务的需求。通过微调,模型能够学习到与任务相关的特定知识,并进一步提高在该任务上的性能。 GPT模型的优势在于其强大的生成能力和对上下文信息的捕捉能力。这使得GPT模型在自然语言生成、文本摘要、对话系统等领域具有广泛的应用前景。同时,GPT模型也面临一些挑战,如计算资源消耗大、训练时间长等问题。为了解决这些问题,研究人员不断提出新的优化方法和扩展模型架构,如GPT-2、GPT-3等,以进一步提高模型的性能和效率。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值