多线程(一)

2018-07-19  本文已影响1人  紫荆秋雪_文

一、常见的多线程

1、pthread

2、NSThread

3、GCD

4、NSOperation

二、GCD(Grand Central Dispatch)

1、GCD中用来执行任务的函数

/**
     同步执行任务

     @param queue 队列
     @param block 任务
*/
dispatch_sync(dispatch_queue_t  _Nonnull queue, block)
/**
     异步执行任务

     @param queue 队列
     @param block 任务
*/
dispatch_async(dispatch_queue_t  _Nonnull queue, block)

2、GCD的队列
1、并发队列(Concurrent Dispatch Queue)

三、GCD实战

1、同步主队列

/**
 同步 主队列
 */
- (void)gcd_syncMain_Test {
    //0.当前线程和当前队列
    dispatch_queue_t currentQ = dispatch_get_current_queue();
    //1.创建主队列
    dispatch_queue_t queue = dispatch_get_main_queue();
    NSLog(@"任务1:%@--当前队列:%p\n", [NSThread currentThread], currentQ);
    //2.在同步串行队列中执行任务
    dispatch_sync(queue, ^{
        for (int i = 0; i < 5; i++) {
            NSLog(@"任务2:中第%d任务---当前线程:%@--当前队列:%p", i, [NSThread currentThread], queue);
        }
        
    });
    NSLog(@"\n");
    for (int i = 0; i < 5; i++) {
        NSLog(@"任务3:%@--当前队列:%p", [NSThread currentThread], currentQ);
    }
}
2018-07-19 00:35:47.881613+0800 01-GCD[5387:594727] 任务1:<NSThread: 0x604000067100>{number = 1, name = main}--当前队列:0x11469ae80
崩溃

2、同步串行队列

/**
 同步串行队列
 */
- (void)gcd_syncSerial_Test {
    //0.当前线程和当前队列
    dispatch_queue_t currentQ = dispatch_get_current_queue();
    //1.创建串行队列
    dispatch_queue_t queue = dispatch_queue_create("queueSerial", DISPATCH_QUEUE_SERIAL);
    NSLog(@"任务1:%@--当前队列:%p\n", [NSThread currentThread], currentQ);
    //2.在同步串行队列中执行任务
    dispatch_sync(queue, ^{
        for (int i = 0; i < 5; i++) {
            NSLog(@"任务2:中第%d任务---当前线程:%@--当前队列:%p", i, [NSThread currentThread], queue);
        }
        
    });
    NSLog(@"\n");
    for (int i = 0; i < 5; i++) {
        NSLog(@"任务3:%@--当前队列:%p", [NSThread currentThread], currentQ);
    }
}
2018-07-19 01:13:05.972097+0800 01-GCD[5559:620371] 任务1:<NSThread: 0x600000065040>{number = 1, name = main}--当前队列:0x11018ce80

2018-07-19 01:13:05.972518+0800 01-GCD[5559:620371] 任务2:中第0任务---当前线程:<NSThread: 0x600000065040>{number = 1, name = main}--当前队列:0x604000143910
2018-07-19 01:13:05.973389+0800 01-GCD[5559:620371] 任务2:中第1任务---当前线程:<NSThread: 0x600000065040>{number = 1, name = main}--当前队列:0x604000143910
2018-07-19 01:13:05.973741+0800 01-GCD[5559:620371] 任务2:中第2任务---当前线程:<NSThread: 0x600000065040>{number = 1, name = main}--当前队列:0x604000143910
2018-07-19 01:13:05.974822+0800 01-GCD[5559:620371] 任务2:中第3任务---当前线程:<NSThread: 0x600000065040>{number = 1, name = main}--当前队列:0x604000143910
2018-07-19 01:13:05.975176+0800 01-GCD[5559:620371] 任务2:中第4任务---当前线程:<NSThread: 0x600000065040>{number = 1, name = main}--当前队列:0x604000143910
2018-07-19 01:13:05.975299+0800 01-GCD[5559:620371] 
2018-07-19 01:13:05.975428+0800 01-GCD[5559:620371] 任务3:<NSThread: 0x600000065040>{number = 1, name = main}--当前队列:0x11018ce80
2018-07-19 01:13:05.975545+0800 01-GCD[5559:620371] 任务3:<NSThread: 0x600000065040>{number = 1, name = main}--当前队列:0x11018ce80
2018-07-19 01:13:05.975786+0800 01-GCD[5559:620371] 任务3:<NSThread: 0x600000065040>{number = 1, name = main}--当前队列:0x11018ce80
2018-07-19 01:13:05.976651+0800 01-GCD[5559:620371] 任务3:<NSThread: 0x600000065040>{number = 1, name = main}--当前队列:0x11018ce80
2018-07-19 01:13:05.976986+0800 01-GCD[5559:620371] 任务3:<NSThread: 0x600000065040>{number = 1, name = main}--当前队列:0x11018ce80

3、同步并行队列

/**
 同步并行队列
 */
- (void)gcd_syncGlobal_Test {
    //0.当前线程和当前队列
    dispatch_queue_t currentQ = dispatch_get_current_queue();
    //1.创建并行队列(全局队列也是一种并行队列)
    dispatch_queue_t queue = dispatch_get_global_queue(0, 0);
    NSLog(@"任务1:%@--当前队列:%p\n", [NSThread currentThread], currentQ);
    //2.在同步并行队列中执行任务
    dispatch_sync(queue, ^{
        for (int i = 0; i < 5; i++) {
            NSLog(@"任务2:中第%d任务---当前线程:%@--当前队列:%p", i, [NSThread currentThread], queue);
        }
        
    });
    NSLog(@"\n");
    for (int i = 0; i < 5; i++) {
        NSLog(@"任务3:%@--当前队列:%p", [NSThread currentThread], currentQ);
    }
}
2018-07-19 01:29:17.816357+0800 01-GCD[5612:630100] 任务1:<NSThread: 0x60400006c980>{number = 1, name = main}--当前队列:0x10f470e80

2018-07-19 01:29:17.816665+0800 01-GCD[5612:630100] 任务2:中第0任务---当前线程:<NSThread: 0x60400006c980>{number = 1, name = main}--当前队列:0x10f472500
2018-07-19 01:29:17.816829+0800 01-GCD[5612:630100] 任务2:中第1任务---当前线程:<NSThread: 0x60400006c980>{number = 1, name = main}--当前队列:0x10f472500
2018-07-19 01:29:17.816985+0800 01-GCD[5612:630100] 任务2:中第2任务---当前线程:<NSThread: 0x60400006c980>{number = 1, name = main}--当前队列:0x10f472500
2018-07-19 01:29:17.817825+0800 01-GCD[5612:630100] 任务2:中第3任务---当前线程:<NSThread: 0x60400006c980>{number = 1, name = main}--当前队列:0x10f472500
2018-07-19 01:29:17.819165+0800 01-GCD[5612:630100] 任务2:中第4任务---当前线程:<NSThread: 0x60400006c980>{number = 1, name = main}--当前队列:0x10f472500
2018-07-19 01:29:17.820390+0800 01-GCD[5612:630100] 
2018-07-19 01:29:17.820808+0800 01-GCD[5612:630100] 任务3:<NSThread: 0x60400006c980>{number = 1, name = main}--当前队列:0x10f470e80
2018-07-19 01:29:17.820923+0800 01-GCD[5612:630100] 任务3:<NSThread: 0x60400006c980>{number = 1, name = main}--当前队列:0x10f470e80
2018-07-19 01:29:17.821028+0800 01-GCD[5612:630100] 任务3:<NSThread: 0x60400006c980>{number = 1, name = main}--当前队列:0x10f470e80
2018-07-19 01:29:17.821291+0800 01-GCD[5612:630100] 任务3:<NSThread: 0x60400006c980>{number = 1, name = main}--当前队列:0x10f470e80
2018-07-19 01:29:17.821423+0800 01-GCD[5612:630100] 任务3:<NSThread: 0x60400006c980>{number = 1, name = main}--当前队列:0x10f470e80

4、异步串行队列

/**
 异步串行队列
 */
- (void)gcd_asyncSerial_Test {
    //0.当前线程和当前队列
    dispatch_queue_t currentQ = dispatch_get_current_queue();
    //1.手动创建串行队列
    dispatch_queue_t queue = dispatch_queue_create("asyncSerial", DISPATCH_QUEUE_SERIAL);
    NSLog(@"任务1:%@--当前队列:%p\n", [NSThread currentThread], currentQ);
    //2.在同步并行队列中执行任务
    dispatch_async(queue, ^{
        for (int i = 0; i < 5; i++) {
            NSLog(@"任务2:中第%d任务---当前线程:%@--当前队列:%p", i, [NSThread currentThread], queue);
        }
        
    });
    NSLog(@"\n");
    for (int i = 0; i < 5; i++) {
        NSLog(@"任务3:%@--当前队列:%p", [NSThread currentThread], currentQ);
    }
}
2018-07-19 01:38:53.699845+0800 01-GCD[5663:636377] 任务1:<NSThread: 0x60000006bac0>{number = 1, name = main}--当前队列:0x10c0d7e80

2018-07-19 01:38:53.700075+0800 01-GCD[5663:636377] 
2018-07-19 01:38:53.700202+0800 01-GCD[5663:636451] 任务2:中第0任务---当前线程:<NSThread: 0x604000465b80>{number = 4, name = (null)}--当前队列:0x6040001569a0
2018-07-19 01:38:53.700432+0800 01-GCD[5663:636451] 任务2:中第1任务---当前线程:<NSThread: 0x604000465b80>{number = 4, name = (null)}--当前队列:0x6040001569a0
2018-07-19 01:38:53.700435+0800 01-GCD[5663:636377] 任务3:<NSThread: 0x60000006bac0>{number = 1, name = main}--当前队列:0x10c0d7e80
2018-07-19 01:38:53.700589+0800 01-GCD[5663:636451] 任务2:中第2任务---当前线程:<NSThread: 0x604000465b80>{number = 4, name = (null)}--当前队列:0x6040001569a0
2018-07-19 01:38:53.700676+0800 01-GCD[5663:636377] 任务3:<NSThread: 0x60000006bac0>{number = 1, name = main}--当前队列:0x10c0d7e80
2018-07-19 01:38:53.700719+0800 01-GCD[5663:636451] 任务2:中第3任务---当前线程:<NSThread: 0x604000465b80>{number = 4, name = (null)}--当前队列:0x6040001569a0
2018-07-19 01:38:53.700792+0800 01-GCD[5663:636377] 任务3:<NSThread: 0x60000006bac0>{number = 1, name = main}--当前队列:0x10c0d7e80
2018-07-19 01:38:53.700846+0800 01-GCD[5663:636451] 任务2:中第4任务---当前线程:<NSThread: 0x604000465b80>{number = 4, name = (null)}--当前队列:0x6040001569a0
2018-07-19 01:38:53.701907+0800 01-GCD[5663:636377] 任务3:<NSThread: 0x60000006bac0>{number = 1, name = main}--当前队列:0x10c0d7e80
2018-07-19 01:38:53.703963+0800 01-GCD[5663:636377] 任务3:<NSThread: 0x60000006bac0>{number = 1, name = main}--当前队列:0x10c0d7e80
/**
 异步串行队列
 */
- (void)gcd_asyncSerial_Test {
    //0.当前线程和当前队列
    dispatch_queue_t currentQ = dispatch_get_current_queue();
    //1.获取主队列
    dispatch_queue_t queue = dispatch_get_main_queue();
    NSLog(@"任务1:%@--当前队列:%p\n", [NSThread currentThread], currentQ);
    //2.在同步并行队列中执行任务
    dispatch_async(queue, ^{
        for (int i = 0; i < 5; i++) {
            NSLog(@"任务2:中第%d任务---当前线程:%@--当前队列:%p", i, [NSThread currentThread], queue);
        }
        
    });
    NSLog(@"\n");
    for (int i = 0; i < 5; i++) {
        NSLog(@"任务3:%@--当前队列:%p", [NSThread currentThread], currentQ);
    }
}
2018-07-19 01:46:21.216192+0800 01-GCD[5700:641200] 任务1:<NSThread: 0x600000067b80>{number = 1, name = main}--当前队列:0x111b23e80

2018-07-19 01:46:21.216456+0800 01-GCD[5700:641200] 
2018-07-19 01:46:21.216593+0800 01-GCD[5700:641200] 任务3:<NSThread: 0x600000067b80>{number = 1, name = main}--当前队列:0x111b23e80
2018-07-19 01:46:21.216711+0800 01-GCD[5700:641200] 任务3:<NSThread: 0x600000067b80>{number = 1, name = main}--当前队列:0x111b23e80
2018-07-19 01:46:21.216859+0800 01-GCD[5700:641200] 任务3:<NSThread: 0x600000067b80>{number = 1, name = main}--当前队列:0x111b23e80
2018-07-19 01:46:21.217054+0800 01-GCD[5700:641200] 任务3:<NSThread: 0x600000067b80>{number = 1, name = main}--当前队列:0x111b23e80
2018-07-19 01:46:21.217519+0800 01-GCD[5700:641200] 任务3:<NSThread: 0x600000067b80>{number = 1, name = main}--当前队列:0x111b23e80
2018-07-19 01:46:21.218070+0800 01-GCD[5700:641200] 任务2:中第0任务---当前线程:<NSThread: 0x600000067b80>{number = 1, name = main}--当前队列:0x111b23e80
2018-07-19 01:46:21.218608+0800 01-GCD[5700:641200] 任务2:中第1任务---当前线程:<NSThread: 0x600000067b80>{number = 1, name = main}--当前队列:0x111b23e80
2018-07-19 01:46:21.219841+0800 01-GCD[5700:641200] 任务2:中第2任务---当前线程:<NSThread: 0x600000067b80>{number = 1, name = main}--当前队列:0x111b23e80
2018-07-19 01:46:21.220003+0800 01-GCD[5700:641200] 任务2:中第3任务---当前线程:<NSThread: 0x600000067b80>{number = 1, name = main}--当前队列:0x111b23e80
2018-07-19 01:46:21.220561+0800 01-GCD[5700:641200] 任务2:中第4任务---当前线程:<NSThread: 0x600000067b80>{number = 1, name = main}--当前队列:0x111b23e80

5、异步并行队列

/**
 异步并行队列
 */
- (void)gcd_asyncConcurrent_Test {
    //0.当前线程和当前队列
    dispatch_queue_t currentQ = dispatch_get_current_queue();
    //1.创建并行队列
    dispatch_queue_t queue = dispatch_queue_create("asyncCONCURRENT", DISPATCH_QUEUE_CONCURRENT);
    NSLog(@"任务1:%@--当前队列:%p\n", [NSThread currentThread], currentQ);
    //2.在同步并行队列中执行任务
    dispatch_async(queue, ^{
        for (int i = 0; i < 5; i++) {
            NSLog(@"任务2:中第%d任务---当前线程:%@--当前队列:%p", i, [NSThread currentThread], queue);
        }
        
    });
    NSLog(@"\n");
    for (int i = 0; i < 5; i++) {
        NSLog(@"任务3:%@--当前队列:%p", [NSThread currentThread], currentQ);
    }
}
2018-07-19 01:53:55.849240+0800 01-GCD[5735:646211] 任务1:<NSThread: 0x60400007ee40>{number = 1, name = main}--当前队列:0x109aa8e80

2018-07-19 01:53:55.849447+0800 01-GCD[5735:646211] 
2018-07-19 01:53:55.849488+0800 01-GCD[5735:646255] 任务2:中第0任务---当前线程:<NSThread: 0x604000468e80>{number = 3, name = (null)}--当前队列:0x604000153820
2018-07-19 01:53:55.849680+0800 01-GCD[5735:646211] 任务3:<NSThread: 0x60400007ee40>{number = 1, name = main}--当前队列:0x109aa8e80
2018-07-19 01:53:55.849783+0800 01-GCD[5735:646255] 任务2:中第1任务---当前线程:<NSThread: 0x604000468e80>{number = 3, name = (null)}--当前队列:0x604000153820
2018-07-19 01:53:55.850067+0800 01-GCD[5735:646211] 任务3:<NSThread: 0x60400007ee40>{number = 1, name = main}--当前队列:0x109aa8e80
2018-07-19 01:53:55.850155+0800 01-GCD[5735:646255] 任务2:中第2任务---当前线程:<NSThread: 0x604000468e80>{number = 3, name = (null)}--当前队列:0x604000153820
2018-07-19 01:53:55.850663+0800 01-GCD[5735:646211] 任务3:<NSThread: 0x60400007ee40>{number = 1, name = main}--当前队列:0x109aa8e80
2018-07-19 01:53:55.851082+0800 01-GCD[5735:646255] 任务2:中第3任务---当前线程:<NSThread: 0x604000468e80>{number = 3, name = (null)}--当前队列:0x604000153820
2018-07-19 01:53:55.851373+0800 01-GCD[5735:646211] 任务3:<NSThread: 0x60400007ee40>{number = 1, name = main}--当前队列:0x109aa8e80
2018-07-19 01:53:55.852096+0800 01-GCD[5735:646255] 任务2:中第4任务---当前线程:<NSThread: 0x604000468e80>{number = 3, name = (null)}--当前队列:0x604000153820
2018-07-19 01:53:55.852750+0800 01-GCD[5735:646211] 任务3:<NSThread: 0x60400007ee40>{number = 1, name = main}--当前队列:0x109aa8e80

6、子线程死锁

/**
 子线程串行队列死锁
 */
- (void)gcd_asyncLock_Test {
    //0.当前线程和当前队列
    dispatch_queue_t currentQ = dispatch_get_current_queue();
    //1.创建并行队列
    dispatch_queue_t queue = dispatch_queue_create("asyncLock", DISPATCH_QUEUE_SERIAL);
    NSLog(@"任务1");
    //2.在同步并行队列中执行任务
    dispatch_async(queue, ^{
        NSLog(@"任务2");
        dispatch_sync(queue, ^{
            NSLog(@"任务3");
        });
        
    });
    NSLog(@"任务4");
}
2018-07-19 02:13:25.627098+0800 01-GCD[5930:662760] 任务1
2018-07-19 02:13:25.627295+0800 01-GCD[5930:662760] 任务4
2018-07-19 02:13:25.627313+0800 01-GCD[5930:662829] 任务2
(lldb) 

四、小结

五、队列组

/**
 异步并发执行任务1、任务2,
 等任务1、任务2都执行完毕后,再回到主线程执行任务3
 */
- (void)taskFun {
    //1.创建队列组
    dispatch_group_t group = dispatch_group_create();
    //2.创建并发队列
    dispatch_queue_t queue = dispatch_queue_create("queue", DISPATCH_QUEUE_CONCURRENT);
    //3.在队列组中异步执行任务
    dispatch_group_async(group, queue, ^{
        for (int i = 0; i < 5; i++) {
            NSLog(@"任务1---%@", [NSThread currentThread]);
        }
    });
    
    dispatch_group_async(group, queue, ^{
        for (int i = 0; i < 5; i++) {
            NSLog(@"任务2---%@", [NSThread currentThread]);
        }
    });
    
    dispatch_group_notify(group, dispatch_get_main_queue(), ^{
        for (int i = 0; i < 5; i++) {
            NSLog(@"任务3---%@", [NSThread currentThread]);
        }
    });
    
}
2018-07-19 22:30:25.586603+0800 02-队列组[1481:70343] 任务1---<NSThread: 0x60400007ebc0>{number = 3, name = (null)}
2018-07-19 22:30:25.586603+0800 02-队列组[1481:70416] 任务2---<NSThread: 0x604000264640>{number = 4, name = (null)}
2018-07-19 22:30:25.586828+0800 02-队列组[1481:70343] 任务1---<NSThread: 0x60400007ebc0>{number = 3, name = (null)}
2018-07-19 22:30:25.586848+0800 02-队列组[1481:70416] 任务2---<NSThread: 0x604000264640>{number = 4, name = (null)}
2018-07-19 22:30:25.587274+0800 02-队列组[1481:70343] 任务1---<NSThread: 0x60400007ebc0>{number = 3, name = (null)}
2018-07-19 22:30:25.587307+0800 02-队列组[1481:70416] 任务2---<NSThread: 0x604000264640>{number = 4, name = (null)}
2018-07-19 22:30:25.587445+0800 02-队列组[1481:70343] 任务1---<NSThread: 0x60400007ebc0>{number = 3, name = (null)}
2018-07-19 22:30:25.588589+0800 02-队列组[1481:70416] 任务2---<NSThread: 0x604000264640>{number = 4, name = (null)}
2018-07-19 22:30:25.590428+0800 02-队列组[1481:70343] 任务1---<NSThread: 0x60400007ebc0>{number = 3, name = (null)}
2018-07-19 22:30:25.591197+0800 02-队列组[1481:70416] 任务2---<NSThread: 0x604000264640>{number = 4, name = (null)}
2018-07-19 22:30:25.591991+0800 02-队列组[1481:70295] 任务3---<NSThread: 0x604000065e00>{number = 1, name = main}
2018-07-19 22:30:25.592272+0800 02-队列组[1481:70295] 任务3---<NSThread: 0x604000065e00>{number = 1, name = main}
2018-07-19 22:30:25.592861+0800 02-队列组[1481:70295] 任务3---<NSThread: 0x604000065e00>{number = 1, name = main}
2018-07-19 22:30:25.593492+0800 02-队列组[1481:70295] 任务3---<NSThread: 0x604000065e00>{number = 1, name = main}
2018-07-19 22:30:25.595441+0800 02-队列组[1481:70295] 任务3---<NSThread: 0x604000065e00>{number = 1, name = main}

六、多线程和RunLoop

实践1

- (void)gcdRunloopTest {
    //1.创建并发队列
    dispatch_queue_t queue = dispatch_queue_create("queue", DISPATCH_QUEUE_CONCURRENT);
    //2.异步执行任务
    dispatch_async(queue, ^{
        NSLog(@"任务1");
        [self performSelector:@selector(taskTest) withObject:nil afterDelay:.0];
        NSLog(@"任务3");
    });
}

- (void)taskTest {
    NSLog(@"任务2");
}
2018-07-19 22:37:14.672885+0800 02-队列组[1563:75572] 任务1
2018-07-19 22:37:14.673153+0800 02-队列组[1563:75572] 任务3

下面更换一下performSelector:withObject:方法

- (void)gcdRunloopTest {
    //1.创建并发队列
    dispatch_queue_t queue = dispatch_queue_create("queue", DISPATCH_QUEUE_CONCURRENT);
    //2.异步执行任务
    dispatch_async(queue, ^{
        NSLog(@"任务1");
//        [self performSelector:@selector(taskTest) withObject:nil afterDelay:.0];
        [self performSelector:@selector(taskTest) withObject:nil];
        NSLog(@"任务3");
    });
}

- (void)taskTest {
    NSLog(@"任务2");
}
2018-07-19 22:39:34.639733+0800 02-队列组[1594:77477] 任务1
2018-07-19 22:39:34.639951+0800 02-队列组[1594:77477] 任务2
2018-07-19 22:39:34.640234+0800 02-队列组[1594:77477] 任务3
performSelector:withObject:afterDelay:方法是NSRunLoop.h文件中的方法
performSelector:withObject方法是NSObject.h文件中的方法,所以这个方法底层会转成
objc_msgSend(self, @selector(taskTest))消息来发送;
- (void)gcdRunloopTest {
    //1.创建并发队列
    dispatch_queue_t queue = dispatch_queue_create("queue", DISPATCH_QUEUE_CONCURRENT);
    //2.异步执行任务
    dispatch_async(queue, ^{
        NSLog(@"任务1");
        [self performSelector:@selector(taskTest) withObject:nil afterDelay:.0];
        NSLog(@"任务3");
        //必须给RunLoop中添加port、Observer、Timer后才能保住线程
        [[NSRunLoop currentRunLoop] addPort:[[NSPort alloc] init] forMode:NSDefaultRunLoopMode];
        //开启线程
        [[NSRunLoop currentRunLoop] runMode:NSDefaultRunLoopMode beforeDate:[NSDate distantFuture]];
    });
}

- (void)taskTest {
    NSLog(@"任务2");
}
打印输出:
2018-07-19 22:54:27.041532+0800 02-队列组[1787:88148] 任务1
2018-07-19 22:54:27.042103+0800 02-队列组[1787:88148] 任务3
2018-07-19 22:54:27.042587+0800 02-队列组[1787:88148] 任务2

实例2

- (void)gcdRunloopTest {
    
    NSThread *thread = [[NSThread alloc] initWithBlock:^{
        NSLog(@"任务1");
    }];
    [thread start];
    [self performSelector:@selector(taskTest) onThread:thread withObject:nil waitUntilDone:YES];
    NSLog(@"任务3");
}

- (void)taskTest {
    NSLog(@"任务2");
}

2018-07-19 23:00:02.872430+0800 02-队列组[1857:92702] 任务1
2018-07-19 23:00:02.888592+0800 02-队列组[1857:92626] *** Terminating app due to uncaught exception 'NSDestinationInvalidException', reason: '*** -[ViewController performSelector:onThread:withObject:waitUntilDone:modes:]: target thread exited while waiting for the perform'
- (void)gcdRunloopTest {
    
    NSThread *thread = [[NSThread alloc] initWithBlock:^{
        NSLog(@"任务1");
        //必须给RunLoop中添加port、Observer、Timer后才能保住线程
        [[NSRunLoop currentRunLoop] addPort:[[NSPort alloc] init] forMode:NSDefaultRunLoopMode];
        //开启线程
        [[NSRunLoop currentRunLoop] runMode:NSDefaultRunLoopMode beforeDate:[NSDate distantFuture]];
    }];
    [thread start];
    [self performSelector:@selector(taskTest) onThread:thread withObject:nil waitUntilDone:YES];
    NSLog(@"任务3");
}

- (void)taskTest {
    NSLog(@"任务2");
}
2018-07-19 23:04:16.362816+0800 02-队列组[1930:96441] 任务1
2018-07-19 23:04:16.363482+0800 02-队列组[1930:96441] 任务2
2018-07-19 23:04:16.363770+0800 02-队列组[1930:96357] 任务3
上一篇 下一篇

猜你喜欢

热点阅读