GCD的详解

2019-05-14  本文已影响0人  WavesFisherman

开始GCD之前我们先来了解下任务和队列的概念

任务

任务在程序里面可以理解为你写的一段代码, 执行任务就是运行代码,关键在于如何执行任务
这里就有同步执行和异步执行的概念了

队列(Dispatch Queue)

队列.png

串行队列 (Serial Dispatch Queue)

串行队列.png

并行队列(Concurrent Dispatch Queue)

并行队列.png

GCD 的创建和使用

// 串行队列
dispatch_queue_t queue = dispatch_queue_create("com.example.gcd.serial", DISPATCH_QUEUE_SERIAL);
// 并行队列
dispatch_queue_t queue = dispatch_queue_create("com.example.gcd.concurrent", DISPATCH_QUEUE_CONCURRENT);
//全局队列
dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
//主队列
dispatch_queue_t queue = dispatch_get_main_queue();
//同步执行
dispatch_sync(queue, ^{

});
//异步执行
dispatch_async(queue, ^{
        
});

上面说了4种队列,2种执行方式,那么他们的组合肯定有多种,来写点代码运行看看效果吧
1、 同步执行串行队列

NSLog(@"--- begin ---");
    
    dispatch_queue_t serialQueue = dispatch_queue_create("com.example.gcd.serial", DISPATCH_QUEUE_SERIAL);
    
    for (NSInteger i = 0; i < 10; i++) {
        dispatch_sync(serialQueue, ^{
            NSLog(@"%ld, 当前线程 : %@", i, [NSThread currentThread]);
        });
    }
    
NSLog(@"--- end ---");

日志打印

2019-05-14 16:03:01.382002+0800 GCDDemo[5717:153795] --- begin ---
2019-05-14 16:03:01.382222+0800 GCDDemo[5717:153795] 0, 当前线程 : <NSThread: 0x6000023313c0>{number = 1, name = main}
2019-05-14 16:03:01.382349+0800 GCDDemo[5717:153795] 1, 当前线程 : <NSThread: 0x6000023313c0>{number = 1, name = main}
2019-05-14 16:03:01.382464+0800 GCDDemo[5717:153795] 2, 当前线程 : <NSThread: 0x6000023313c0>{number = 1, name = main}
2019-05-14 16:03:01.382563+0800 GCDDemo[5717:153795] 3, 当前线程 : <NSThread: 0x6000023313c0>{number = 1, name = main}
2019-05-14 16:03:01.382659+0800 GCDDemo[5717:153795] 4, 当前线程 : <NSThread: 0x6000023313c0>{number = 1, name = main}
2019-05-14 16:03:01.382785+0800 GCDDemo[5717:153795] 5, 当前线程 : <NSThread: 0x6000023313c0>{number = 1, name = main}
2019-05-14 16:03:01.382879+0800 GCDDemo[5717:153795] 6, 当前线程 : <NSThread: 0x6000023313c0>{number = 1, name = main}
2019-05-14 16:03:01.382971+0800 GCDDemo[5717:153795] 7, 当前线程 : <NSThread: 0x6000023313c0>{number = 1, name = main}
2019-05-14 16:03:01.383061+0800 GCDDemo[5717:153795] 8, 当前线程 : <NSThread: 0x6000023313c0>{number = 1, name = main}
2019-05-14 16:03:01.395531+0800 GCDDemo[5717:153795] 9, 当前线程 : <NSThread: 0x6000023313c0>{number = 1, name = main}
2019-05-14 16:03:01.395652+0800 GCDDemo[5717:153795] --- end ---

结果分析:依次执行, 没有开辟新线程
2、同步执行并行队列

NSLog(@"--- begin ---");
    
    dispatch_queue_t concurrentQueue = dispatch_queue_create("com.example.gcd.serial", DISPATCH_QUEUE_CONCURRENT);
    
    for (NSInteger i = 0; i < 10; i++) {
        dispatch_sync(concurrentQueue, ^{
            NSLog(@"%ld, 当前线程 : %@", i, [NSThread currentThread]);
        });
    }
    
NSLog(@"--- end ---");
2019-05-14 16:04:34.245949+0800 GCDDemo[5739:154761] --- begin ---
2019-05-14 16:04:34.246151+0800 GCDDemo[5739:154761] 0, 当前线程 : <NSThread: 0x60000055d3c0>{number = 1, name = main}
2019-05-14 16:04:34.246264+0800 GCDDemo[5739:154761] 1, 当前线程 : <NSThread: 0x60000055d3c0>{number = 1, name = main}
2019-05-14 16:04:34.246373+0800 GCDDemo[5739:154761] 2, 当前线程 : <NSThread: 0x60000055d3c0>{number = 1, name = main}
2019-05-14 16:04:34.246484+0800 GCDDemo[5739:154761] 3, 当前线程 : <NSThread: 0x60000055d3c0>{number = 1, name = main}
2019-05-14 16:04:34.246593+0800 GCDDemo[5739:154761] 4, 当前线程 : <NSThread: 0x60000055d3c0>{number = 1, name = main}
2019-05-14 16:04:34.246705+0800 GCDDemo[5739:154761] 5, 当前线程 : <NSThread: 0x60000055d3c0>{number = 1, name = main}
2019-05-14 16:04:34.246801+0800 GCDDemo[5739:154761] 6, 当前线程 : <NSThread: 0x60000055d3c0>{number = 1, name = main}
2019-05-14 16:04:34.246891+0800 GCDDemo[5739:154761] 7, 当前线程 : <NSThread: 0x60000055d3c0>{number = 1, name = main}
2019-05-14 16:04:34.246982+0800 GCDDemo[5739:154761] 8, 当前线程 : <NSThread: 0x60000055d3c0>{number = 1, name = main}
2019-05-14 16:04:34.258913+0800 GCDDemo[5739:154761] 9, 当前线程 : <NSThread: 0x60000055d3c0>{number = 1, name = main}
2019-05-14 16:04:34.259039+0800 GCDDemo[5739:154761] --- end ---

结果分析: 同上
3、同步执行全局队列

NSLog(@"--- begin ---");
    
    dispatch_queue_t globalQueue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
    
    for (NSInteger i = 0; i < 10; i++) {
        dispatch_sync(globalQueue, ^{
            NSLog(@"%ld, 当前线程 : %@", i, [NSThread currentThread]);
        });
    }
    
NSLog(@"--- end ---");
2019-05-14 16:06:44.980750+0800 GCDDemo[5767:155906] --- begin ---
2019-05-14 16:06:44.981023+0800 GCDDemo[5767:155906] 0, 当前线程 : <NSThread: 0x6000016993c0>{number = 1, name = main}
2019-05-14 16:06:44.981168+0800 GCDDemo[5767:155906] 1, 当前线程 : <NSThread: 0x6000016993c0>{number = 1, name = main}
2019-05-14 16:06:44.981307+0800 GCDDemo[5767:155906] 2, 当前线程 : <NSThread: 0x6000016993c0>{number = 1, name = main}
2019-05-14 16:06:44.981410+0800 GCDDemo[5767:155906] 3, 当前线程 : <NSThread: 0x6000016993c0>{number = 1, name = main}
2019-05-14 16:06:44.981526+0800 GCDDemo[5767:155906] 4, 当前线程 : <NSThread: 0x6000016993c0>{number = 1, name = main}
2019-05-14 16:06:44.981640+0800 GCDDemo[5767:155906] 5, 当前线程 : <NSThread: 0x6000016993c0>{number = 1, name = main}
2019-05-14 16:06:44.981738+0800 GCDDemo[5767:155906] 6, 当前线程 : <NSThread: 0x6000016993c0>{number = 1, name = main}
2019-05-14 16:06:44.981833+0800 GCDDemo[5767:155906] 7, 当前线程 : <NSThread: 0x6000016993c0>{number = 1, name = main}
2019-05-14 16:06:44.981976+0800 GCDDemo[5767:155906] 8, 当前线程 : <NSThread: 0x6000016993c0>{number = 1, name = main}
2019-05-14 16:06:45.016921+0800 GCDDemo[5767:155906] 9, 当前线程 : <NSThread: 0x6000016993c0>{number = 1, name = main}
2019-05-14 16:06:45.017021+0800 GCDDemo[5767:155906] --- end ---

结果分析:同上
4、同步执行主队列

NSLog(@"--- begin ---");
    
    dispatch_queue_t mainQueue = dispatch_get_main_queue();
    
    dispatch_sync(mainQueue, ^{
        NSLog(@"1");
    });
    
    dispatch_sync(mainQueue, ^{
        NSLog(@"2");
    });
    
    dispatch_sync(mainQueue, ^{
        NSLog(@"3");
    });
    
NSLog(@"--- end ---");
2019-05-14 15:19:00.807434+0800 GCDDemo[5154:130087] --- begin ---
(lldb) 
崩溃截图.png

结果崩溃了
这边涉及到了线程死锁的概念, 简单说一下:这段代码本身(这里称做任务F,下同)就先添加再主队列里, NSLog(@"1"), NSLog(@"2"),NSLog(@"3")分别一次后添加到主队列里面, NSLog(@"1")这个任务在等待任务F执行完, 任务F要想执行完那必须等到NSLog(@"1"), NSLog(@"2"), NSLog(@"3")着三个任务都执行完了才能执行完, 这样就存在了任务F和NSLog(@"1")互相等待, 这就形成了主线程的死锁.(建议自己详细了解一下线程的死锁)
5、异步执行串行队列

NSLog(@"--- begin ---");
    
    dispatch_queue_t serialQueue = dispatch_queue_create("com.example.gcd.serial", DISPATCH_QUEUE_SERIAL);
    
    for (NSInteger i = 0; i < 10; i++) {
        dispatch_async(serialQueue, ^{
            NSLog(@"%ld, 当前线程 : %@", i, [NSThread currentThread]);
        });
    }
    
NSLog(@"--- end ---");
2019-05-14 16:08:38.492805+0800 GCDDemo[5793:157042] --- begin ---
2019-05-14 16:08:38.492977+0800 GCDDemo[5793:157042] --- end ---
2019-05-14 16:08:38.493042+0800 GCDDemo[5793:157082] 0, 当前线程 : <NSThread: 0x600001c69480>{number = 3, name = (null)}
2019-05-14 16:08:38.493195+0800 GCDDemo[5793:157082] 1, 当前线程 : <NSThread: 0x600001c69480>{number = 3, name = (null)}
2019-05-14 16:08:38.493331+0800 GCDDemo[5793:157082] 2, 当前线程 : <NSThread: 0x600001c69480>{number = 3, name = (null)}
2019-05-14 16:08:38.493441+0800 GCDDemo[5793:157082] 3, 当前线程 : <NSThread: 0x600001c69480>{number = 3, name = (null)}
2019-05-14 16:08:38.493559+0800 GCDDemo[5793:157082] 4, 当前线程 : <NSThread: 0x600001c69480>{number = 3, name = (null)}
2019-05-14 16:08:38.493667+0800 GCDDemo[5793:157082] 5, 当前线程 : <NSThread: 0x600001c69480>{number = 3, name = (null)}
2019-05-14 16:08:38.493780+0800 GCDDemo[5793:157082] 6, 当前线程 : <NSThread: 0x600001c69480>{number = 3, name = (null)}
2019-05-14 16:08:38.493911+0800 GCDDemo[5793:157082] 7, 当前线程 : <NSThread: 0x600001c69480>{number = 3, name = (null)}
2019-05-14 16:08:38.508214+0800 GCDDemo[5793:157082] 8, 当前线程 : <NSThread: 0x600001c69480>{number = 3, name = (null)}
2019-05-14 16:08:38.508361+0800 GCDDemo[5793:157082] 9, 当前线程 : <NSThread: 0x600001c69480>{number = 3, name = (null)}

结果分析: 先走的开始和结束, 任务依次执行, 开辟了新线程,只开辟了一条新线程
6、异步执行并行队列

NSLog(@"--- begin ---");
    
    dispatch_queue_t concurrentQueue = dispatch_queue_create("com.example.gcd.serial", DISPATCH_QUEUE_CONCURRENT);
    
    for (NSInteger i = 0; i < 10; i++) {
        dispatch_async(concurrentQueue, ^{
            NSLog(@"%ld, 当前线程 : %@", i, [NSThread currentThread]);
        });
    }
    
NSLog(@"--- end ---");
2019-05-14 16:14:01.097373+0800 GCDDemo[5837:159234] --- begin ---
2019-05-14 16:14:01.097566+0800 GCDDemo[5837:159234] --- end ---
2019-05-14 16:14:01.097710+0800 GCDDemo[5837:159276] 0, 当前线程 : <NSThread: 0x600003aa4200>{number = 3, name = (null)}
2019-05-14 16:14:01.097712+0800 GCDDemo[5837:159278] 3, 当前线程 : <NSThread: 0x600003a84a40>{number = 6, name = (null)}
2019-05-14 16:14:01.097710+0800 GCDDemo[5837:159275] 1, 当前线程 : <NSThread: 0x600003ae3f80>{number = 5, name = (null)}
2019-05-14 16:14:01.097783+0800 GCDDemo[5837:159283] 4, 当前线程 : <NSThread: 0x600003aab5c0>{number = 7, name = (null)}
2019-05-14 16:14:01.097783+0800 GCDDemo[5837:159277] 2, 当前线程 : <NSThread: 0x600003abfb00>{number = 4, name = (null)}
2019-05-14 16:14:01.097793+0800 GCDDemo[5837:159284] 5, 当前线程 : <NSThread: 0x600003aab580>{number = 8, name = (null)}
2019-05-14 16:14:01.097827+0800 GCDDemo[5837:159285] 6, 当前线程 : <NSThread: 0x600003abfb40>{number = 9, name = (null)}
2019-05-14 16:14:01.097882+0800 GCDDemo[5837:159286] 7, 当前线程 : <NSThread: 0x600003a84ac0>{number = 10, name = (null)}
2019-05-14 16:14:01.097895+0800 GCDDemo[5837:159275] 9, 当前线程 : <NSThread: 0x600003ae3f80>{number = 5, name = (null)}
2019-05-14 16:14:01.097909+0800 GCDDemo[5837:159278] 8, 当前线程 : <NSThread: 0x600003a84a40>{number = 6, name = (null)}

结果分析:顺序就是乱的了, 开辟了新线程, 开辟了不止一条新线程
7、异步执行全局队列

NSLog(@"--- begin ---");
    
    dispatch_queue_t globalQueue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
    
    for (NSInteger i = 0; i < 10; i++) {
        dispatch_async(globalQueue, ^{
            NSLog(@"%ld", i);
        });
    }
    
NSLog(@"--- end ---");
2019-05-14 15:59:03.987523+0800 GCDDemo[5675:151762] --- begin ---
2019-05-14 15:59:03.987725+0800 GCDDemo[5675:151762] --- end ---
2019-05-14 15:59:03.987863+0800 GCDDemo[5675:151803] 1, 当前线程 : <NSThread: 0x60000090c380>{number = 4, name = (null)}
2019-05-14 15:59:03.987862+0800 GCDDemo[5675:151806] 3, 当前线程 : <NSThread: 0x60000097f700>{number = 6, name = (null)}
2019-05-14 15:59:03.987865+0800 GCDDemo[5675:151804] 2, 当前线程 : <NSThread: 0x600000919b80>{number = 5, name = (null)}
2019-05-14 15:59:03.987887+0800 GCDDemo[5675:151805] 0, 当前线程 : <NSThread: 0x600000914080>{number = 3, name = (null)}
2019-05-14 15:59:03.987895+0800 GCDDemo[5675:151823] 4, 当前线程 : <NSThread: 0x60000094ed40>{number = 7, name = (null)}
2019-05-14 15:59:03.987928+0800 GCDDemo[5675:151824] 5, 当前线程 : <NSThread: 0x60000090c3c0>{number = 8, name = (null)}
2019-05-14 15:59:03.988011+0800 GCDDemo[5675:151825] 6, 当前线程 : <NSThread: 0x60000094eec0>{number = 9, name = (null)}
2019-05-14 15:59:03.988014+0800 GCDDemo[5675:151806] 8, 当前线程 : <NSThread: 0x60000097f700>{number = 6, name = (null)}
2019-05-14 15:59:03.988037+0800 GCDDemo[5675:151805] 9, 当前线程 : <NSThread: 0x600000914080>{number = 3, name = (null)}
2019-05-14 15:59:03.988040+0800 GCDDemo[5675:151826] 7, 当前线程 : <NSThread: 0x60000097f900>{number = 10, name = (null)}

结果分析:同上
8、异步执行主队列

NSLog(@"--- begin ---");
    
    dispatch_queue_t mainQueue = dispatch_get_main_queue();
    
    for (NSInteger i = 0; i < 10; i++) {
        dispatch_async(mainQueue, ^{
            NSLog(@"%ld, 当前线程 : %@", i, [NSThread currentThread]);
        });
    }
    
NSLog(@"--- end ---");
2019-05-14 15:56:57.099676+0800 GCDDemo[5648:150470] --- begin ---
2019-05-14 15:56:57.099889+0800 GCDDemo[5648:150470] --- end ---
2019-05-14 15:56:57.112562+0800 GCDDemo[5648:150470] 0, 当前线程 : <NSThread: 0x600001ce13c0>{number = 1, name = main}
2019-05-14 15:56:57.112749+0800 GCDDemo[5648:150470] 1, 当前线程 : <NSThread: 0x600001ce13c0>{number = 1, name = main}
2019-05-14 15:56:57.112850+0800 GCDDemo[5648:150470] 2, 当前线程 : <NSThread: 0x600001ce13c0>{number = 1, name = main}
2019-05-14 15:56:57.112945+0800 GCDDemo[5648:150470] 3, 当前线程 : <NSThread: 0x600001ce13c0>{number = 1, name = main}
2019-05-14 15:56:57.113067+0800 GCDDemo[5648:150470] 4, 当前线程 : <NSThread: 0x600001ce13c0>{number = 1, name = main}
2019-05-14 15:56:57.113166+0800 GCDDemo[5648:150470] 5, 当前线程 : <NSThread: 0x600001ce13c0>{number = 1, name = main}
2019-05-14 15:56:57.113297+0800 GCDDemo[5648:150470] 6, 当前线程 : <NSThread: 0x600001ce13c0>{number = 1, name = main}
2019-05-14 15:56:57.113417+0800 GCDDemo[5648:150470] 7, 当前线程 : <NSThread: 0x600001ce13c0>{number = 1, name = main}
2019-05-14 15:56:57.127392+0800 GCDDemo[5648:150470] 8, 当前线程 : <NSThread: 0x600001ce13c0>{number = 1, name = main}
2019-05-14 15:56:57.127536+0800 GCDDemo[5648:150470] 9, 当前线程 : <NSThread: 0x600001ce13c0>{number = 1, name = main}

结果分析:先执行的开始和结束, 中间的任务是按顺序执行的,没有开辟新线程

GCD之Group

dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
     dispatch_group_t group = dispatch_group_create();
     dispatch_group_async(group, queue, ^{
         NSLog(@"%@",group);
         NSLog(@"blok0");
     });
     dispatch_group_async(group, queue, ^{
         NSLog(@"block1");
     });
     dispatch_group_async(group, queue, ^{
         NSLog(@"block2");
     });
     dispatch_group_notify(group, queue, ^{
         NSLog(@"done");
     });
//     dispatch_release(group); // 只有在MRC下才这么写,ARC下会自动管理
2019-05-14 16:24:25.308830+0800 GCDDemo[5922:163218] block1
2019-05-14 16:24:25.308830+0800 GCDDemo[5922:163217] block2
2019-05-14 16:24:25.308942+0800 GCDDemo[5922:163219] <OS_dispatch_group: 0x600003bc90e0>
2019-05-14 16:24:25.309028+0800 GCDDemo[5922:163219] blok0
2019-05-14 16:24:25.309138+0800 GCDDemo[5922:163219] done

结果分析: 最后才执行的dispatch_group_notify中的任务(应用场景:一个页面有多个数据请求,等所有的请求都回调回来后才刷新界面)

GCD之Barrier

    dispatch_queue_t queue = dispatch_queue_create("com.example.gcd.ForBarrier", DISPATCH_QUEUE_CONCURRENT);
    for (NSInteger i = 0; i < 5; i++) {
        dispatch_async(queue, ^{
            NSLog(@"%ld", i);
        });
    }
    dispatch_barrier_async(queue, ^{
        NSLog(@"--- ---");
    });
    for (NSInteger i = 5; i < 10; i++) {
        dispatch_async(queue, ^{
            NSLog(@"%ld", i);
        });
    }
2019-05-14 16:34:06.856068+0800 GCDDemo[6028:168004] 3
2019-05-14 16:34:06.856057+0800 GCDDemo[6028:168005] 1
2019-05-14 16:34:06.856057+0800 GCDDemo[6028:168003] 0
2019-05-14 16:34:06.856057+0800 GCDDemo[6028:168006] 2
2019-05-14 16:34:06.856151+0800 GCDDemo[6028:168010] 4
2019-05-14 16:34:06.856279+0800 GCDDemo[6028:168010] --- ---
2019-05-14 16:34:06.856373+0800 GCDDemo[6028:168010] 5
2019-05-14 16:34:06.856381+0800 GCDDemo[6028:168006] 6
2019-05-14 16:34:06.856389+0800 GCDDemo[6028:168003] 7
2019-05-14 16:34:06.856403+0800 GCDDemo[6028:168004] 8
2019-05-14 16:34:06.856422+0800 GCDDemo[6028:168011] 9

结果分析:barrier就是栏的意思, 就像一个挡板以它界限分割开了, 上面的任务异步执行, 下面的任务异步执行

GCD之Semaphore

// 使用信号量可以做到并行队列串行执行 ,而且当信号量为1时是按照代码顺序执行的
- (void)GCD_semaphore{
    dispatch_semaphore_t semaphore = dispatch_semaphore_create(1);
    dispatch_queue_t globalQueue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);

    dispatch_async(globalQueue, ^{
        dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER);//当信号量>=1时,才会执行下面的代码,等待信号量-1
        NSLog(@"first start");
        NSLog(@"first end");
        dispatch_semaphore_signal(semaphore);//信号量+1
    });
    dispatch_async(globalQueue, ^{
        dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER);
        NSLog(@"second start");
        NSLog(@"second end");
        dispatch_semaphore_signal(semaphore);//信号量+1
    });
    dispatch_async(globalQueue, ^{
        dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER);
        NSLog(@"third start");
        NSLog(@"third end");
        dispatch_semaphore_signal(semaphore);//信号量+1
    });
}
2019-05-14 16:39:09.310763+0800 GCDDemo[6083:170514] first start
2019-05-14 16:39:09.310924+0800 GCDDemo[6083:170514] first end
2019-05-14 16:39:09.311018+0800 GCDDemo[6083:170512] second start
2019-05-14 16:39:09.311106+0800 GCDDemo[6083:170512] second end
2019-05-14 16:39:09.311184+0800 GCDDemo[6083:170513] third start
2019-05-14 16:39:09.311247+0800 GCDDemo[6083:170513] third end

结果分析: 按顺序依次执行 (这就是异步里面的同步)
semaphore个人使用总结:

 dispatch_semaphore_wait 函数的作用:
 1、如果dsema信号量的值大于0,该函数所处线程就继续执行下面的语句,
 并且将信号量的值减1; 
 2、如果desema的值为0,那么这个函数就阻塞当前线程等待timeout(注意timeout的类型为dispatch_time_t,
 需要传入对应的类型参数),如果等待的期间desema的值被dispatch_semaphore_signal函数加1了,且该函数(即dispatch_semaphore_wait)所处线程获得了信号量,那么就继续向下执行并将信号量减1。
 
 3、如果等待期间没有获取到信号量或者信号量的值一直为0,那么等到timeout时,其所处线程自动执行其后语句。

转载请注明出处
原文链接: https://www.jianshu.com/p/8321f35e30b9
参考资料: https://www.jianshu.com/p/2d57c72016c6

补充:

GCD之定时器

    dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
    
    dispatch_source_t timer = dispatch_source_create(DISPATCH_SOURCE_TYPE_TIMER, 0, 0, queue);
    /*
     para1: 间隔几秒
     para2: leeway (翻译:最小的余地)精确度
     */
    dispatch_source_set_timer(timer, DISPATCH_TIME_NOW, 1.0 * NSEC_PER_SEC, 0.1 * NSEC_PER_SEC);
    dispatch_source_set_event_handler(timer, ^{
        //要执行的任务
        NSLog(@"***");
    });
    
    //开始执行定时器
    dispatch_resume(timer);

运行完之后你会发现没有日志输出
原因是我们创建的这个_timer在这段代码执行完后就被销毁了,可以看出GCD并没有管理它的内存,并没有强持有它,所以我们需要自己想办法让它不被销毁

@property (nonatomic, strong) dispatch_source_t timer;

- (void)GCD_timer {
    dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
    
//    dispatch_source_t timer = dispatch_source_create(DISPATCH_SOURCE_TYPE_TIMER, 0, 0, queue);
    //GCD创建的timer必须被持有
    self.timer = dispatch_source_create(DISPATCH_SOURCE_TYPE_TIMER, 0, 0, queue);
    /*
     para1: 间隔几秒
     para2: leeway (翻译:最小的余地)精确度
     */
    dispatch_source_set_timer(self.timer, DISPATCH_TIME_NOW, 1.0 * NSEC_PER_SEC, 0.1 * NSEC_PER_SEC);
    dispatch_source_set_event_handler(self.timer, ^{
        //要执行的任务
        NSLog(@"***");
    });
    
    //开始执行定时器
    dispatch_resume(self.timer);
}
2019-05-14 20:01:49.960536+0800 GCDDemo[8032:248654] ***
2019-05-14 20:01:50.995122+0800 GCDDemo[8032:248654] ***
2019-05-14 20:01:52.048355+0800 GCDDemo[8032:248653] ***
2019-05-14 20:01:52.960705+0800 GCDDemo[8032:248654] ***
2019-05-14 20:01:53.960540+0800 GCDDemo[8032:248654] ***
2019-05-14 20:01:55.051170+0800 GCDDemo[8032:248654] ***
2019-05-14 20:01:56.058094+0800 GCDDemo[8032:248666] ***

参考链接:https://www.jianshu.com/p/69e2b9169365

上一篇下一篇

猜你喜欢

热点阅读