美文网首页
iOS GCD 示例代码

iOS GCD 示例代码

作者: Yuency | 来源:发表于2018-08-31 16:35 被阅读22次

    前言:

    1.多线程是面试中很骚的一个环节。
    2.遇到一些奇怪的逻辑,说不定就会用上多线程了。
    3.每次遇到多线程的问题,我总是遍访群贤。
    4.我从没有使用过多线程

    代码地址 https://github.com/gityuency/ObjectiveCTools
    【类名:GCDViewController】

    场景1

    多个异步请求并发执行,在都执行完之后再做下一步操作。


    场景1.png
    /*
     场景1: 有 M 个网络请求, 等 M 个网络请求都结束之后, 再进行第 M + 1 个请求
     备注: 异步请求的 block 里面不要再添加其他异步请求
     */
    - (IBAction)CGD_Group:(id)sender {
        
        dispatch_group_t group = dispatch_group_create();
        
        dispatch_group_async(group, dispatch_get_global_queue(0, 0), ^{
            
            //这里面已经是一个 异步线程 正在执行的代码范围
            //这里面可以放入大量的计算来造成任务很重的假象
            //如果在这个区域再放入异步操作, 那就是异步套异步, 那就是另外一个故事了..
            
            sleep(2);
            NSLog(@"1 当前线程%@",[NSThread currentThread]);
        });
        
        dispatch_group_async(group, dispatch_get_global_queue(0, 0), ^{
            sleep(5);
            NSLog(@"2 当前线程%@",[NSThread currentThread]);
        });
        
        dispatch_group_async(group, dispatch_get_global_queue(0, 0), ^{
            sleep(3);
            NSLog(@"3 当前线程%@",[NSThread currentThread]);
        });
        
        dispatch_group_notify(group, dispatch_get_main_queue(), ^{
            NSLog(@"任务全部完成,当前线程 %@",[NSThread currentThread]);
        });
    }
    

    场景2

    多个网络请求并发执行,在都执行完成之后,再做下一步操作,这里的异步请求来自于三方或者官方。


    场景2.png
    /*
     场景1: 有 M 个请求,等 M 个请求完成之后, 再进行第 M + 1 个请求
     备注: 如果这个请求不是 dispatch_group_async, 那该怎么做.
     */
    - (IBAction)GCD_Enter_Leave:(id)sender {
        
        dispatch_group_t group = dispatch_group_create();
        
        dispatch_group_enter(group);
        NSURL *url = [NSURL URLWithString:@"https://github.com/AFNetworking/AFNetworking.git"];
        NSURLRequest *request = [NSURLRequest requestWithURL:url];
        NSURLSession *session=[NSURLSession sharedSession];
        NSURLSessionDataTask *dataTask=[session dataTaskWithRequest:request completionHandler:^(NSData * _Nullable data, NSURLResponse * _Nullable response, NSError * _Nullable error) {
            NSLog(@"3 当前线程%@",[NSThread currentThread]);
            dispatch_group_leave(group);
        }];
        [dataTask resume];
        
        
        dispatch_group_enter(group);
        NSURL *url2 = [NSURL URLWithString:@"https://github.com/oa414/objc-zen-book-cn"];
        NSURLRequest *request2 = [NSURLRequest requestWithURL:url2];
        NSURLSession *session2 = [NSURLSession sharedSession];
        NSURLSessionDataTask *dataTask2 = [session2 dataTaskWithRequest:request2 completionHandler:^(NSData * _Nullable data, NSURLResponse * _Nullable response, NSError * _Nullable error) {
            NSLog(@"4 当前线程%@",[NSThread currentThread]);
            dispatch_group_leave(group);
        }];
        [dataTask2 resume];
        
        
        dispatch_group_enter(group);
        dispatch_group_async(group, dispatch_get_global_queue(0, 0), ^{
            sleep(3);
            NSLog(@"1 当前线程%@",[NSThread currentThread]);
            dispatch_group_leave(group);
        });
        
        dispatch_group_enter(group);
        dispatch_group_async(group, dispatch_get_global_queue(0, 0), ^{
            sleep(2);
            NSLog(@"2 当前线程%@",[NSThread currentThread]);
            dispatch_group_leave(group);
        });
        
        dispatch_group_notify(group, dispatch_get_main_queue(), ^{
            NSLog(@"任务全部完成,当前线程 %@",[NSThread currentThread]);
        });
    }
    

    场景3

    多个任务按照顺序执行


    场景3.png
    /*
     (异步线程 并发执行 然后阻塞 然后并发执行)
     1,有 m 个网络请求。
     2,先并发执行其中 n 个。
     3,待这n个请求完成之后再执行第 n+1 个请求。
     4,然后等 第 n+1 个请求完成后再并发执行剩下的 m-(n+1) 个请求。
     */
    - (IBAction)GCD_Barrier:(id)sender {
        
        // 创建队列
        dispatch_queue_t queue = dispatch_queue_create("我的名字", DISPATCH_QUEUE_CONCURRENT);
        dispatch_async(queue, ^{
            sleep(3);
            NSLog(@"1 当前线程%@",[NSThread currentThread]);
        });
        dispatch_async(queue, ^{
            sleep(5);
            NSLog(@"2 当前线程%@",[NSThread currentThread]);
        });
        dispatch_async(queue, ^{
            sleep(2);
            NSLog(@"3 当前线程%@",[NSThread currentThread]);
        });
        dispatch_barrier_async(queue, ^{
            NSLog(@"处理任务 1 2 3");
        });
        dispatch_async(queue, ^{
            sleep(2);
            NSLog(@"4 当前线程%@",[NSThread currentThread]);
        });
        dispatch_async(queue, ^{
            sleep(4);
            NSLog(@"5 当前线程%@",[NSThread currentThread]);
        });
        dispatch_barrier_async(queue, ^{
            NSLog(@"处理任务 4 5");
        });
    }
    

    场景4

    异步线程控制并发数。


    场景4.png
    /*
     场景1: 系统现在有 2 个空闲线程可以用, 但是同一时间 有 3 个线程要同时访问, 如何安排线程线程访问?
     场景2: 同一时间要下载很多图片, 每次下载都会开辟一个新线程, 但是开辟太多线程会卡顿, 如何控制最大开辟线程数?
     备注: 如果这个请求不是 dispatch_group_async, 那该怎么做.
     */
    - (IBAction)GCD_Semaphore:(id)sender {
        
        //创建信号量,参数:信号量的初值,如果小于0则会返回NULL crate的value表示,最多几个资源可访问
        dispatch_semaphore_t semaphore = dispatch_semaphore_create(2);
        dispatch_queue_t quene = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
        
        //任务4 (注意,种情况属于异步线程里面又开了一个异步线程)
        dispatch_async(quene, ^{
            dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER);
            NSLog(@"➡️任务 4 当前线程%@",[NSThread currentThread]);
            NSURL *url = [NSURL URLWithString:@"https://www.163.com/"];
            NSURLRequest *request = [NSURLRequest requestWithURL:url];
            NSURLSession *session= [NSURLSession sharedSession];
            NSURLSessionDataTask *dataTask=[session dataTaskWithRequest:request completionHandler:^(NSData * _Nullable data, NSURLResponse * _Nullable response, NSError * _Nullable error) {
                NSLog(@"✅任务 4 当前线程%@",[NSThread currentThread]);
                dispatch_semaphore_signal(semaphore);
            }];
            [dataTask resume];
        });
        
        //任务1
        dispatch_async(quene, ^{
            //等待降低信号量 -1
            dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER);
            NSLog(@"➡️任务 1 当前线程%@",[NSThread currentThread]);
            sleep(1);
            NSLog(@"✅任务 1 当前线程%@",[NSThread currentThread]);
            //提高信号量 +1
            dispatch_semaphore_signal(semaphore);
        });
        
        //任务2
        dispatch_async(quene, ^{
            dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER);
            NSLog(@"➡️任务 2 当前线程%@",[NSThread currentThread]);
            sleep(1);
            NSLog(@"✅任务 2 当前线程%@",[NSThread currentThread]);
            dispatch_semaphore_signal(semaphore);
        });
        
        //任务5
        dispatch_async(quene, ^{
            dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER);
            NSLog(@"➡️任务 5 当前线程%@",[NSThread currentThread]);
            NSURL *url = [NSURL URLWithString:@"https://github.com/oa414/objc-zen-book-cn"];
            NSURLRequest *request = [NSURLRequest requestWithURL:url];
            NSURLSession *session= [NSURLSession sharedSession];
            NSURLSessionDataTask *dataTask=[session dataTaskWithRequest:request completionHandler:^(NSData * _Nullable data, NSURLResponse * _Nullable response, NSError * _Nullable error) {
                NSLog(@"✅任务 5 当前线程%@",[NSThread currentThread]);
                dispatch_semaphore_signal(semaphore);
            }];
            [dataTask resume];
        });
        
        //任务3
        dispatch_async(quene, ^{
            dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER);
            NSLog(@"➡️任务 3 当前线程%@",[NSThread currentThread]);
            sleep(1);
            NSLog(@"✅任务 3 当前线程%@",[NSThread currentThread]);
            dispatch_semaphore_signal(semaphore);
        });
    }
    

    相关文章

      网友评论

          本文标题:iOS GCD 示例代码

          本文链接:https://www.haomeiwen.com/subject/wvwvbftx.html