多线程NSThread、NSOperation、GCD

今天我来详细介绍一下多线程的用法 包括线程整个的生命周期等等

1.0 NSThread 三种表现形式 详情看下面

- (void)viewDidLoad {
    [super viewDidLoad];
    
    NSLog(@"打印当前线程%@",[NSThread currentThread]);
    
    // 1. NSThread
    // NSThread 线程有三种表现形式
    // 1.1 创建对象  需要手动开启线程
    NSThread * thread = [[NSThread alloc]initWithTarget:self selector:@selector(CommonSelector1) object:@"abc"];
    [thread start];
    
    // 1.2 从主线程中分离出一个线程 不需要手动开启
    [NSThread detachNewThreadSelector:@selector(CommonSelector2) toTarget:self withObject:@"abc"];
    
    // 1.3 从后台开辟一个线程
    [self performSelectorInBackground:@selector(CommonSelector3) withObject:@"abc"];
}

-(void)CommonSelector1{
    NSLog(@"打印当前线程----CommonSelector1 = %@",[NSThread currentThread]);
}

-(void)CommonSelector2{
    NSLog(@"打印当前线程----CommonSelector2 = %@",[NSThread currentThread]);
}

-(void)CommonSelector3{
    NSLog(@"打印当前线程----CommonSelector3 = %@",[NSThread currentThread]);
}
// 打印结果
2017-06-01 15:54:32.580 IOS-多线程2[10320:231085] 打印当前线程<NSThread: 0x600000065a80>{number = 1, name = main}
2017-06-01 15:54:32.581 IOS-多线程2[10320:231163] 打印当前线程----CommonSelector1 = <NSThread: 0x600000070d00>{number = 3, name = (null)}
2017-06-01 15:54:32.581 IOS-多线程2[10320:231164] 打印当前线程----CommonSelector2 = <NSThread: 0x600000070d40>{number = 4, name = (null)}
2017-06-01 15:54:32.583 IOS-多线程2[10320:231165] 打印当前线程----CommonSelector3 = <NSThread: 0x600000066f40>{number = 5, name = (null)}

2.0 GCD 这个好玩 这个复杂

2.1 异步async 下 dispatch_get_global_queue 与dispatch_get_main_queue 执行顺序

    dispatch_async(dispatch_get_main_queue(), ^{
        NSLog(@"在主队列中执行任务时不会开启新的线程的");
    });
    // dispatch_get_global_queue 队列的优先级  DISPATCH_QUEUE_PRIORITY_HIGH  高中低
    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH,0), ^{
        
        for (int i = 0; i<5; i++) {
            
            NSLog(@"--5--%@",[NSThread currentThread]);
        }
    });
    // dispatch_get_global_queue 队列的优先级  DISPATCH_QUEUE_PRIORITY_HIGH  高中低
    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH,0), ^{
        for (int i = 0; i<5; i++) {
            NSLog(@"--4--%@",[NSThread currentThread]);
        }
    });
//  输出结果
2017-06-04 12:17:10.381 NSOperation[2767:52779] --5--<NSThread: 0x608000076ac0>{number = 4, name = (null)}
2017-06-04 12:17:10.381 NSOperation[2767:52776] --4--<NSThread: 0x6080000765c0>{number = 3, name = (null)}
2017-06-04 12:17:20.249 NSOperation[2767:52779] --5--<NSThread: 0x608000076ac0>{number = 4, name = (null)}
2017-06-04 12:17:20.250 NSOperation[2767:52776] --4--<NSThread: 0x6080000765c0>{number = 3, name = (null)}
2017-06-04 12:17:22.807 NSOperation[2767:52776] --4--<NSThread: 0x6080000765c0>{number = 3, name = (null)}
2017-06-04 12:17:22.807 NSOperation[2767:52779] --5--<NSThread: 0x608000076ac0>{number = 4, name = (null)}
2017-06-04 12:17:27.115 NSOperation[2767:52717] 在主队列中执行任务时不会开启新的线程的

2.2 注意一种情况

// 这种情况下 只会输出  NSLog(@"1");  然后程序crash 这是一个死锁
    NSLog(@"1");
    dispatch_sync(dispatch_get_main_queue(), ^{
        NSLog(@"在主队列中执行任务时不会开启新的线程的");
    });
    NSLog(@"2");

3.0 GCD 的总结

        1. dispatch_queue_t queue = dispatch_queue_create("queue", NULL);
           1.1> 串行队列不论是在sync 还是 async 中 执行任务 任务是依次进行的  但是在async 开启了新的线程
     
        2. dispatch_queue_t queue = dispatch_queue_create("myqueue", DISPATCH_QUEUE_CONCURRENT);
           2.1> 并行队列在sync 中不回开启新的线程 在 async 中会开启新的线程
     
        3. dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
           3.1> 全局队列在sync 中不会开启新的线程 在 async 中会开启新的线程
     
        4. 在async 中 如果 dispatch_get_main_queue 与 dispatch_get_global_queue 同时存在
           4.1> 执行的先后顺序是 先执行 dispatch_get_global_queue 然后执行 dispatch_get_main_queue

        5. 在dispatch_get_main_queue 添加sync 任务会造成死锁 
           在dispatch_get_main_queue 添加async 任务不会造成卡死 不会开启新的线程 任务是逐次完成的

线程的生命周期

   /*
       线程的生命周期
       1. 首先我们会创建一个线程的对象 并将这个对象放到内存中
       2. 然后我们开启线程,那么此时线程会被放倒内存池中,线程处于 准备被调用状态。等待CPU调度
       3. 当CPU 调度该线程  处于线程调度状态 (这里提一个多线程同时调度)
          当CPU 调度其他线程的时候 该线程处于 被调度状态
       4. 线程阻塞:调度sleep/等待线程阻塞时
       5. 线程的死亡:1.线程任务执行完成 自动死亡 2.线程异常/或者强制退出
   
    
       // 关于线程这一块,不建议用互斥锁 占内存 容易造成死锁
       互斥锁 是在一段时间内锁这线程 使其他线程不能访问 会占用大量的内存 不建议用
    */

NSOperation

我在工程中介绍了 NSOperation 的两种形式 还有一种自定义的没写,因为写了也没什么卵用 做项目根本 就不会用到

所有的代码都放在github: https://github.com/tianbinbin/GCD-NSThread-NSOperation 喜欢的麻烦点个赞 😍

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 203,098评论 5 476
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,213评论 2 380
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 149,960评论 0 336
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,519评论 1 273
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,512评论 5 364
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,533评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,914评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,574评论 0 256
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,804评论 1 296
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,563评论 2 319
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,644评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,350评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,933评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,908评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,146评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,847评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,361评论 2 342

推荐阅读更多精彩内容