iOS底层学习-day-19

前言-OC-多线程篇

我是一名iOS开发者, iOS底层 菜鸟的进阶之路30天。

runloop常驻线程-封装

OC封装

  • MJPermenantThread.h
#import <Foundation/Foundation.h>

typedef void (^MJPermenantThreadTask)(void);

@interface MJPermenantThread : NSObject

/**
 开启线程
 */
//- (void)run;

/**
 在当前子线程执行一个任务
 */
- (void)executeTask:(MJPermenantThreadTask)task;

/**
 结束线程
 */
- (void)stop;

@end
  • MJPermenantThread.m
#import "MJPermenantThread.h"

/** MJThread **/
@interface MJThread : NSThread

@end

@implementation MJThread
- (void)dealloc {
    NSLog(@"%s", __func__);
}
@end

/** MJPermenantThread **/
@interface MJPermenantThread ()

@property (strong, nonatomic) MJThread *innerThread;
@property (assign, nonatomic, getter=isStopped) BOOL stopped;

@end

@implementation MJPermenantThread
#pragma mark - public methods
- (instancetype)init {
    if (self = [super init]) {
        self.stopped = NO;
        
        __weak typeof(self) weakSelf = self;
        
        self.innerThread = [[MJThread alloc] initWithBlock:^{
            [[NSRunLoop currentRunLoop] addPort:[[NSPort alloc] init] forMode:NSDefaultRunLoopMode];
            
            while (weakSelf && !weakSelf.isStopped) {
                [[NSRunLoop currentRunLoop] runMode:NSDefaultRunLoopMode beforeDate:[NSDate distantFuture]];
            }
        }];
        
        [self.innerThread start];
    }
    return self;
}

//- (void)run
//{
//    if (!self.innerThread) return;
//
//    [self.innerThread start];
//}

- (void)executeTask:(MJPermenantThreadTask)task {
    if (!self.innerThread || !task) return;
    
    [self performSelector:@selector(__executeTask:) onThread:self.innerThread withObject:task waitUntilDone:NO];
}

- (void)stop {
    if (!self.innerThread) return;
    
    [self performSelector:@selector(__stop) onThread:self.innerThread withObject:nil waitUntilDone:YES];
}

- (void)dealloc {
    NSLog(@"%s", __func__);
    [self stop];
}

#pragma mark - private methods

- (void)__stop {
    self.stopped = YES;
    CFRunLoopStop(CFRunLoopGetCurrent());
    self.innerThread = nil;
}

- (void)__executeTask:(MJPermenantThreadTask)task {
    task();
}

@end

C封装

/** MJPermenantThread **/
@interface MJPermenantThread()

@property (strong, nonatomic) MJThread *innerThread;

@end

@implementation MJPermenantThread
#pragma mark - public methods
- (instancetype)init {
    if (self = [super init]) {
        self.innerThread = [[MJThread alloc] initWithBlock:^{
            NSLog(@"begin----");
            
            // 创建上下文(要初始化一下结构体)
            CFRunLoopSourceContext context = {0};
            
            // 创建source
            CFRunLoopSourceRef source = CFRunLoopSourceCreate(kCFAllocatorDefault, 0, &context);
            
            // 往Runloop中添加source
            CFRunLoopAddSource(CFRunLoopGetCurrent(), source, kCFRunLoopDefaultMode);
            
            // 销毁source
            CFRelease(source);
            
            // 启动
            CFRunLoopRunInMode(kCFRunLoopDefaultMode, 1.0e10, false);
            
//            while (weakSelf && !weakSelf.isStopped) {
//                // 第3个参数:returnAfterSourceHandled,设置为true,代表执行完source后就会退出当前loop
//                CFRunLoopRunInMode(kCFRunLoopDefaultMode, 1.0e10, true);
//            }
            
            NSLog(@"end----");
        }];
        
        [self.innerThread start];
    }
    return self;
}

//- (void)run
//{
//    if (!self.innerThread) return;
//
//    [self.innerThread start];
//}

- (void)executeTask:(MJPermenantThreadTask)task {
    if (!self.innerThread || !task) return;
    
    [self performSelector:@selector(__executeTask:) onThread:self.innerThread withObject:task waitUntilDone:NO];
}

- (void)stop {
    if (!self.innerThread) return;
    
    [self performSelector:@selector(__stop) onThread:self.innerThread withObject:nil waitUntilDone:YES];
}

- (void)dealloc {
    NSLog(@"%s", __func__);
    
    [self stop];
}

#pragma mark - private methods
- (void)__stop {
    CFRunLoopStop(CFRunLoopGetCurrent());
    self.innerThread = nil;
}

- (void)__executeTask:(MJPermenantThreadTask)task {
    task();
}

@end

多线程-GCD

GCD 2个用来执行任务的函数dispatch_sync - dispatch_async

  • GCD源码链接

  • 同步的方式执行任务//就是在当前线程做事情

    • dispatch_sync(dispatch_queue_t queue, dispatch_block_t block);
    • queue:队列
    • block:任务
  • 异步的方式执行任务

    • dispatch_async(dispatch_queue_t queue, dispatch_block_t block);

GCD的队列可以分为2大类型

  • 并发队列(Concurrent Dispatch Queue)

    • 可以让多个任务并发(同时)执行(自动开启多个线程同时执行任务)
    • 并发功能只有在异步(dispatch_async)函数下才有效
  • 串行队列(Serial Dispatch Queue)

    • 让任务一个接着一个地执行(一个任务执行完毕后,再执行下一个任务)

GCD有4个术语比较容易混淆:同步、异步、并发、串行

  • 同步异步主要影响:能不能开启新的线程

    • 同步:在当前线程中执行任务,不具备开启新线程的能力
    • 异步:在新的线程中执行任务,具备开启新线程的能力
  • 并发串行主要影响:任务的执行方式

    • 并发:多个任务并发(同时)执行
    • 串行:一个任务执行完毕后,再执行下一个任务
      在这里插入图片描述

GCD的一写判断线程是否死锁

  • dispatch_syncdispatch_async用来控制是否要开启新的线程
    • 队列的类型,决定了任务的执行方式(并发、串行)
      • 并发队列
      • 串行队列
      • 主队列(也是一个串行队列)
  • 例子1 - 以下代码是在主线程执行的,会不会产生死锁?会!
- (void)interview01 {
    // 以下代码是在主线程执行的,会不会产生死锁?会!
    NSLog(@"执行任务1");
    
    dispatch_queue_t queue = dispatch_get_main_queue();
    dispatch_sync(queue, ^{
        NSLog(@"执行任务2");
    });
    
    NSLog(@"执行任务3");
    // 在sync中,往当前的串行队列中添加任务会死锁
}
  • 例子2 - 以下代码是在主线程执行的,会不会产生死锁?不会!
- (void)interview02 {
    // 以下代码是在主线程执行的,会不会产生死锁?不会!
    NSLog(@"执行任务1");
    
    dispatch_queue_t queue = dispatch_get_main_queue();
    dispatch_async(queue, ^{
        NSLog(@"执行任务2");
    });
    
    NSLog(@"执行任务3");
    
    // 执行任务1 > 执行任务3 > 执行任务2
}
  • 例子3 - 以下代码是在主线程执行的,会不会产生死锁?会!
- (void)interview03 {
    // 以下代码是在主线程执行的,会不会产生死锁?会!
    NSLog(@"执行任务1");
    
    dispatch_queue_t queue = dispatch_queue_create("myqueu", DISPATCH_QUEUE_SERIAL);
    dispatch_async(queue, ^{ // 0
        NSLog(@"执行任务2");
        
        dispatch_sync(queue, ^{ // 1要等 0执行完,再执行执行任务3
            NSLog(@"执行任务3");
        });
    
        NSLog(@"执行任务4");
    });
    
    NSLog(@"执行任务5");
    // 1 > 5 > 2 > 死锁
}
  • 例子4 - 以下代码是在主线程执行的,会不会产生死锁?不会!
- (void)interview04 {
    // 以下代码是在主线程执行的,会不会产生死锁?不会!
    NSLog(@"执行任务1");
    
    dispatch_queue_t queue = dispatch_queue_create("myqueu", DISPATCH_QUEUE_SERIAL);
//    dispatch_queue_t queue2 = dispatch_queue_create("myqueu2", DISPATCH_QUEUE_CONCURRENT);//不会
    dispatch_queue_t queue2 = dispatch_queue_create("myqueu2", DISPATCH_QUEUE_SERIAL);//不会
    
    dispatch_async(queue, ^{ // 0
        NSLog(@"执行任务2");
        
        dispatch_sync(queue2, ^{ // 1
            NSLog(@"执行任务3");
        });
        
        NSLog(@"执行任务4");
    });
    
    NSLog(@"执行任务5");
    // 1 > 5 > 2 > 3 > 4
}
  • 例子5 - 以下代码是在主线程执行的,会不会产生死锁?不会!
- (void)interview05 {
    // 以下代码是在主线程执行的,会不会产生死锁?不会!
    NSLog(@"执行任务1");
    
    dispatch_queue_t queue = dispatch_queue_create("myqueu", DISPATCH_QUEUE_CONCURRENT);
    
    dispatch_async(queue, ^{ // 0
        NSLog(@"执行任务2");
        
        dispatch_sync(queue, ^{ // 1
            NSLog(@"执行任务3");
        });
        
        NSLog(@"执行任务4");
    });
    
    NSLog(@"执行任务5");
    // 1 > 5 > 2 > 3 > 4
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值