GCD实现和ARC、Blocks、GCD使用范例

Dispatch Queue

通常,应用程序中编写的线程管理用的代码要在系统级实现。

无论编程人员如何努力编写管理线程的代码,在性能方面也不可能胜过XNU内核级所实现的GCD。

用于实现Dispatch Queue而使用的软件组件:

  1. libdispatch 提供技术:Dispatch Queue;
  2. Libc(pthreads) 提供技术:pthread_workqueue;
  3. XNU内核 提供技术:workqueue;

GCD的API全部为包含在libdispatch库中的C语言函数。

Dispatch Queue通过结构体和链表实现为FIFO队列。队列管理师通过dispatch_async函数所追加的Block。

Block先加入Dispatch Continuation这一dispatch_continuation_t类型结构体中,然后在加入FIFO队列中。该Dispatch Continuation用于记忆Block所属的Dispatch Group和其他一些信息,相当于一般常说的执行上下文。

dispatch_set_target_queue函数可以设置Dispatch Queue为另一个Dispatch Queue的目标。可以像串珠子一样,设定多个连接在一起的Dispatch Queue。在连接的最后必须设定为Main Dispatch Queue,或各种优先级的Global Dispatch Queue或是准备用于Serial Dispatch Queue的各种优先级的Global Dispatch Queue。

Main Dispatch Queue在RunLoop中执行Block。

Global Dispatch Queue有8种类型。

ARC、Blocks、GCD使用范例

实现从指定的URL下载数据,在另外的线程中解析该数据并在主线程中使用其解析结果:

NSString *url = @"https://gimg2.baidu.com/image_search/src=http%3A%2F%2Fphoto.16pic.com%2F00%2F54%2F75%2F16pic_5475997_b.jpg&refer=http%3A%2F%2Fphoto.16pic.com&app=2002&size=f9999,10000&q=a80&n=0&g=0n&fmt=jpeg?sec=1617284495&t=3bacab64a5d8233a37c94e2cc7f47492";
//在主线程中,从指定的url开始异步网络下载
NSURL *postUrl = [NSURL URLWithString:url];
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:postUrl];
request.HTTPMethod = @"GET";
[request setTimeoutInterval:15];
request.cachePolicy = NSURLRequestReloadIgnoringLocalCacheData;

NSURLSessionConfiguration *configuration = [NSURLSessionConfiguration defaultSessionConfiguration];
NSURLSession *session = [NSURLSession sessionWithConfiguration:configuration];

NSURLSessionDataTask *task = [session dataTaskWithRequest:request completionHandler:^(NSData * _Nullable data, NSURLResponse * _Nullable response, NSError * _Nullable error)
{
    dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
    dispatch_async(queue, ^
    {
        //不妨碍主线程可长时间处理获取的数据
        dispatch_async(dispatch_get_main_queue(), ^
        {
            //对界面进行反应处理
        });
    });
}];

[task resume];
[session finishTasksAndInvalidate];

Cocoa框架提供了用于异步网络通信的API,所以在网络编程中不可使用线程。务必使用用于异步网络通信的API。

我们基于NSURLSession封装的异步网络请求:

#import <Foundation/Foundation.h>

NS_ASSUME_NONNULL_BEGIN

typedef void (^completeBlock_t) (NSData *data);
typedef void (^errorBlock_t) (NSError *error);

@interface ASyncURLSession : NSURLSession

{
    /**
     *由于ARC有效,所以以下的没有显示附加所有权修饰符的变量,
     *全部为附有__strong修饰符的变量。
     */
    NSMutableData *data;
    completeBlock_t completeBlock_;
    errorBlock_t errorBlock_;
}

+(id)request:(NSString *)requestURL
completeBlock:(completeBlock_t)completeBlock
  errorBlock:(errorBlock_t)errorBlock;

-(id)initWithRequest:(NSString *)requestURL
       completeBlock:(completeBlock_t)completeBlock
          errorBlock:(errorBlock_t)errorBlock;

@end

NS_ASSUME_NONNULL_END

 

上一篇:为什么我的数据库查询越来越慢


下一篇:201871030126-王会娟 常用源代码管理工具与开发工具