iOS开发系列-多线程

iOS创建多线程的4种方式

  • 1 pthread : C语言 只需了解,暂不介绍
  • 2 NSThread
  • 3 GCD
  • 4 NSOperation

特别注意:以下测试方法全部在主线程中调用

方式一:pthread创建方式

该方式暂不介绍

方式二:NSThread创建线程三种方法

  • 对象方法
  • 分类方法
  • 类方法

对象方法

代码示例:

   NSThread *thread = [[NSThread alloc] initWithTarget:self selector:@selector(nslogThread) object:nil];
    //注意启动一个线程并非就一定立即执行,而是处于就绪状态,当系统调度时才真正执行
    [thread start];
- (void) nslogThread {
    sleep(5);
    NSLog(@"%@",[NSThread currentThread]);
  NSLog(@"callBack");
}

分类方法

特别注意:
另外performSelectorOnMainThread方法是NSObject的分类方法,每个NSObject对象都有此方法,
它调用的selector方法是当前调用控件的方法,例如使用UIImageView调用的时候selector就是UIImageView的方法
Object:代表调用方法的参数,不过只能传递一个参数(如果有多个参数请使用对象进行封装)
waitUntilDone:是否线程任务完成才往下边执行
//如果YES,则,阻塞当前线程,直至新开辟线程执行完毕,才往下执行
//如果NO,不阻塞当前线程

    //在当前线程中执行(当前线程为主线程)
    NSLog(@"before");
    [self performSelectorOnMainThread:@selector(nslogThread) withObject:nil waitUntilDone:YES];
    NSLog(@"after");
    //创建新的线程
    //[self performSelectorInBackground:@selector(nslogThread) withObject:nil];
    //2016-05-26 13:04:28.595 NSThread三种方法[46373:1704985] <NSThread: 0x7fb9a2d2d040>{number = 2, name = (null)}

类方法


    //分类方法
    //selector:当前调用控件的方法,
    //target:由哪一个对象执行该方法
    //Object:代表调用方法的参数,不过只能传递一个参数(如果有多个参数请使用对象进行封装)
    [NSThread detachNewThreadSelector:@selector(nslogThread) toTarget:self withObject:nil];
    //2016-05-26 12:45:02.773 NSThread三种方法[45067:1693652] <NSThread: 0x7f92a0f0b250>{number = 2, name = (null)}

方式三:GCD创建线程

首先我们要弄明白GCD中的核心概念
核心概念:

  • 任务
    1 同步任务: 在当前线程中的任务,不会开启新的线程
    2 异步任务:不在当前线程中的任务,会开启新的线程
  • 队列
    1 串行队列
    2 并发队列
    3 全局队列
    4 主队列

串行队列

串行队列-同步任务

-(void)serialQueue_syn{
   
   //1 任务
   void (^task1)(void)=^(){
       
       NSLog(@"task:%d,%@",1,[NSThread currentThread]);
   };
   void (^task2)(void)=^(){
       
       NSLog(@"task:%d,%@",2,[NSThread currentThread]);
   };
   void (^task3)(void)=^(){
       
       NSLog(@"task:%d,%@",3,[NSThread currentThread]);
   };
   
   //2 创建串行队列
   //参数1:该队列的名字
   //参数2:创建何种队列,如果DISPATCH_QUEUE_SERIAL则代表创建串行队列,其中#define DISPATCH_QUEUE_SERIAL NULL,即也可传入NULL
   dispatch_queue_t serialQueue=dispatch_queue_create("serialQueue_syn", DISPATCH_QUEUE_SERIAL);
   
   //3 向队列中添加同步任务
   dispatch_sync(serialQueue, task1);
   dispatch_sync(serialQueue, task2);
   dispatch_sync(serialQueue, task3);
   
   NSLog(@"serialQueue_over");
}

输出结果:
[1913:704162] task:1,<NSThread: 0x13d50c3e0>{number = 1, name = main}
[1913:704162] task:2,<NSThread: 0x13d50c3e0>{number = 1, name = main}
[1913:704162] task:3,<NSThread: 0x13d50c3e0>{number = 1, name = main}
[1913:704162] serialQueue_over

串行队列-异步任务

-(void)serialQueue_asyn{
    
    void (^task1)(void)=^(){
        
        NSLog(@"task:%d,%@",1,[NSThread currentThread]);
    };
    void (^task2)(void)=^(){
        
        NSLog(@"task:%d,%@",2,[NSThread currentThread]);
    };
    void (^task3)(void)=^(){
        
        NSLog(@"task:%d,%@",3,[NSThread currentThread]);
    };
    
    //创建串行队列
    dispatch_queue_t serialQuere=dispatch_queue_create("serialQueue_asyn", NULL);
    
    //向队列中添加异步任务
    dispatch_async(serialQuere, task1);
    dispatch_async(serialQuere, task2);
    dispatch_async(serialQuere, task3);

    NSLog(@"serialQueue_asyn");
}

输出结果:
[1916:704616] serialQueue_asyn
[1916:704631] task:1,<NSThread: 0x15fd6bde0>{number = 2, name = (null)}
[1916:704631] task:2,<NSThread: 0x15fd6bde0>{number = 2, name = (null)}
[1916:704631] task:3,<NSThread: 0x15fd6bde0>{number = 2, name = (null)}

** 串行队列总结:**
在串行队列中,同步任务则不创建新的线程,异步任务创建新的线程(只创建1条),对加入其中的任务,按照加入队列中的顺序执行,不改变任务的执行序列。

并发队列

并发队列-同步任务

-(void)concurrentQueue_syn{
    
    void (^task1)(void)=^(){
        
        NSLog( @"task:%d,%@",1,[NSThread currentThread]);
    };
    void (^task2)(void)=^(){
        
        NSLog( @"task:%d,%@",2,[NSThread currentThread]);
    };
    void (^task3)(void)=^(){
        
        NSLog( @"task:%d,%@",3,[NSThread currentThread]);
    };
    void (^task4)(void)=^(){
        
        NSLog( @"task:%d,%@",4,[NSThread currentThread]);
    };
    void (^task5)(void)=^(){
        
        NSLog( @"task:%d,%@",5,[NSThread currentThread]);
    };
    //2 创建并发队列
    //参数1:队列名字
    //参数2:创建队列类型:DISPATCH_QUEUE_CONCURRENT并发类型
    dispatch_queue_t concurrentQueue=dispatch_queue_create("concurrentQueue_syn", DISPATCH_QUEUE_CONCURRENT);
    
    //3 向队列中添加同步任务
    dispatch_sync(concurrentQueue, task1);
    dispatch_sync(concurrentQueue, task2);
    dispatch_sync(concurrentQueue, task3);
    dispatch_sync(concurrentQueue, task4);
    dispatch_sync(concurrentQueue, task5);
    NSLog(@"concurrent");
}

执行结果:
[1928:709535] task:1,<NSThread: 0x13ee04810>{number = 1, name = main}
[1928:709535] task:2,<NSThread: 0x13ee04810>{number = 1, name = main}
[1928:709535] task:3,<NSThread: 0x13ee04810>{number = 1, name = main}
[1928:709535] task:4,<NSThread: 0x13ee04810>{number = 1, name = main}
[1928:709535] task:5,<NSThread: 0x13ee04810>{number = 1, name = main}
[1928:709535] concurrent

并发队列-异步任务

-(void) concurrentQueue_asyn{
    
    void (^task1)(void)=^(){
      
        NSLog( @"task:%d,%@",1,[NSThread currentThread]);
    };
    void (^task2)(void)=^(){
        
        NSLog( @"task:%d,%@",2,[NSThread currentThread]);
    };
    void (^task3)(void)=^(){
        
        NSLog( @"task:%d,%@",3,[NSThread currentThread]);
    };
    void (^task4)(void)=^(){
        
        NSLog( @"task:%d,%@",4,[NSThread currentThread]);
    };
    void (^task5)(void)=^(){
        
        NSLog( @"task:%d,%@",5,[NSThread currentThread]);
    };
    //创建并发队列
    //参数1:队列名字
    //参数2:创建队列类型:DISPATCH_QUEUE_CONCURRENT并发类型
    dispatch_queue_t concurrentQueue=dispatch_queue_create("concurrentQueue_asyn", DISPATCH_QUEUE_CONCURRENT);
    
    //向队列中添加异步任务
    dispatch_async(concurrentQueue, task1);
    dispatch_async(concurrentQueue, task2);
    dispatch_async(concurrentQueue, task3);
    dispatch_async(concurrentQueue, task4);
    dispatch_async(concurrentQueue, task5);
    
    NSLog(@"concurrent_asyn_over");
}

执行结果:
[1932:710530] concurrent_asyn_over
[1932:710569] task:4,<NSThread: 0x15ce76250>{number = 5, name = (null)}
[1932:710568] task:3,<NSThread: 0x15ce75c60>{number = 4, name = (null)}
[1932:710559] task:2,<NSThread: 0x15ce75b50>{number = 3, name = (null)}
[1932:710560] task:1,<NSThread: 0x15ce71900>{number = 2, name = (null)}
[1932:710570] task:5,<NSThread: 0x15ce773c0>{number = 6, name = (null)}

并发队列总结:
在并发队列中,同步任务不开辟线程,异步任务创建随机创建N条线程,并且任务执行顺序为无序状态

全局队列

全局队列-同步任务

-(void)globalQueue_async{
    
    void (^task1)(void)=^(){
        
        NSLog( @"task:%d,%@",1,[NSThread currentThread]);
    };
    void (^task2)(void)=^(){
        
        NSLog( @"task:%d,%@",2,[NSThread currentThread]);
    };
    void (^task3)(void)=^(){
        
        NSLog( @"task:%d,%@",3,[NSThread currentThread]);
    };
    void (^task4)(void)=^(){
        
        NSLog( @"task:%d,%@",4,[NSThread currentThread]);
    };
    void (^task5)(void)=^(){
        
        NSLog( @"task:%d,%@",5,[NSThread currentThread]);
    };
    
    
    //2 获得全局队列
    dispatch_queue_t globalQueue=dispatch_get_global_queue(0, 0);
    //3 向全局队列中添加异任务
    dispatch_async(globalQueue, task1);
    dispatch_async(globalQueue, task2);
    dispatch_async(globalQueue, task3);
    dispatch_async(globalQueue, task4);
    dispatch_async(globalQueue, task5);
    
    NSLog(@"globalQueue_async");
}

执行结果:
[1954:716253] task:1,<NSThread: 0x14650c350>{number = 1, name = main}
[1954:716253] task:2,<NSThread: 0x14650c350>{number = 1, name = main}
[1954:716253] task:3,<NSThread: 0x14650c350>{number = 1, name = main}
[1954:716253] task:4,<NSThread: 0x14650c350>{number = 1, name = main}
[1954:716253] task:5,<NSThread: 0x14650c350>{number = 1, name = main}
[1954:716253] globalQueue_sync

全局队列-异步任务

-(void)globalQueue_async{
    
    void (^task1)(void)=^(){
        
        NSLog( @"task:%d,%@",1,[NSThread currentThread]);
    };
    void (^task2)(void)=^(){
        
        NSLog( @"task:%d,%@",2,[NSThread currentThread]);
    };
    void (^task3)(void)=^(){
        
        NSLog( @"task:%d,%@",3,[NSThread currentThread]);
    };
    void (^task4)(void)=^(){
        
        NSLog( @"task:%d,%@",4,[NSThread currentThread]);
    };
    void (^task5)(void)=^(){
        
        NSLog( @"task:%d,%@",5,[NSThread currentThread]);
    };
    
    
    //2 获得全局队列
    dispatch_queue_t globalQueue=dispatch_get_global_queue(0, 0);
    //3 向全局队列中添加异任务
    dispatch_async(globalQueue, task1);
    dispatch_async(globalQueue, task2);
    dispatch_async(globalQueue, task3);
    dispatch_async(globalQueue, task4);
    dispatch_async(globalQueue, task5);
    
    NSLog(@"globalQueue_async");
}

执行结果:
[1958:716810] globalQueue_async
[1958:716924] task:3,<NSThread: 0x155dbc1c0>{number = 4, name = (null)}
[1958:716921] task:2,<NSThread: 0x155dbdae0>{number = 3, name = (null)}
[1958:716922] task:1,<NSThread: 0x155db9ba0>{number = 2, name = (null)}
[1958:716926] task:4,<NSThread: 0x155dbd3d0>{number = 5, name = (null)}
[1958:716928] task:5,<NSThread: 0x155dbbd70>{number = 6, name = (null)}

全局队列总结:
在全局队列中,同步任务不开辟线程,异步任务开辟N条随机线程,并且任务执行顺序为无序状态

主队列

主队列-同步任务

-(void)mainQueue_sync{
    
    //创建任务
    void (^task1)(void)=^(){
        
        NSLog( @"task:%d,%@",1,[NSThread currentThread]);
    };
    void (^task2)(void)=^(){
        
        NSLog( @"task:%d,%@",2,[NSThread currentThread]);
    };
    void (^task3)(void)=^(){
        
        NSLog( @"task:%d,%@",3,[NSThread currentThread]);
    };
    void (^task4)(void)=^(){
        
        NSLog( @"task:%d,%@",4,[NSThread currentThread]);
    };
    void (^task5)(void)=^(){
        
        NSLog( @"task:%d,%@",5,[NSThread currentThread]);
    };
    
    //2 获取系统主队列
    dispatch_queue_t mainQueue=dispatch_get_main_queue();
    
    //3 向主队列中添加同步任务
    dispatch_sync(mainQueue, task1);//在此处:一直在等带主线执行完毕,而主线程一直在等待该任务执行完毕
    dispatch_sync(mainQueue, task2);
    dispatch_sync(mainQueue, task3);
    dispatch_sync(mainQueue, task4);
    dispatch_sync(mainQueue, task5);
    
    NSLog(@"mainQueue_sync");
}

输出结果:
什么也没有输出,因为:向主队列中添加同步任务会出现死等状态。

主队列-异步任务

-(void)mainQueue_async{
    
    void (^task1)(void)=^(){
        
        NSLog( @"task:%d,%@",1,[NSThread currentThread]);
    };
    void (^task2)(void)=^(){
        
        NSLog( @"task:%d,%@",2,[NSThread currentThread]);
    };
    void (^task3)(void)=^(){
        
        NSLog( @"task:%d,%@",3,[NSThread currentThread]);
    };
    void (^task4)(void)=^(){
        
        NSLog( @"task:%d,%@",4,[NSThread currentThread]);
    };
    void (^task5)(void)=^(){
        
        NSLog( @"task:%d,%@",5,[NSThread currentThread]);
    };
    
    //2 获取系统主队列
    dispatch_queue_t mainQueue=dispatch_get_main_queue();
    
    //3 向主对列中添加异步任务
    dispatch_async(mainQueue, task1);
    dispatch_async(mainQueue, task2);
    dispatch_async(mainQueue, task3);
    dispatch_async(mainQueue, task4);
    dispatch_async(mainQueue, task5);
    
    NSLog(@"mainQueue_async");
}

输出结果:
mainQueue_async
task:1,<NSThread: 0x134507960>{number = 1, name = main}
task:2,<NSThread: 0x134507960>{number = 1, name = main}
task:3,<NSThread: 0x134507960>{number = 1, name = main}
task:4,<NSThread: 0x134507960>{number = 1, name = main}
task:5,<NSThread: 0x134507960>{number = 1, name = main}

主队列总结:
在主队列中,同步任务会卡死主线程,异步任务不会创建线程,而是在主线程中执行。

方式四:NSOperation创建线程

核心概念:队列NSOperationQueue和任务NSOperation

队列NSOperationQueue分类:

  • 主 队 列:由系统提供,通过[NSOperationQueue new]方式获取
  • 并发队列:程序员创建[[NSOperationQueue alloc] init]方式获取

任务NSOperation分类:

  • NSInvationOperation类型任务
  • NSBlockOperation类型任务

主队列

操作主队列-NSInvationOperation类型任务

-(void)operationQueueAsynDemo1{
    //1 获取主队列
    NSOperationQueue *mainQueue=[NSOperationQueue mainQueue];
    //1 创建invocation任务
    NSInvocationOperation *invocationOper=[[NSInvocationOperation alloc] initWithTarget:self selector:@selector(test:) object:@"mainQueue"];
    //3 向对列中添加任务
    [mainQueue addOperation:invocationOper];
}

-(void)test:(NSString *)info{
    NSLog( @"%@--%@",info,[NSThread currentThread]);
}

输出结果:
主队列[2015:729865] mainQueue--<NSThread: 0x13750c370>{number = 1, name = main}

主队列-NSBlockOperation类型任务

-(void)operationQueueAsynDemo2{
    
    //1 获取主队列
    NSOperationQueue *mainQueue=[NSOperationQueue mainQueue];
    //2 创建block任务
    NSBlockOperation *blockOperation=[NSBlockOperation blockOperationWithBlock:^{
        NSLog(@"-->%@",[NSThread currentThread]);
        
    }];
    //3 向队列中添加block任务
    [mainQueue addOperation:blockOperation];
}

-(void)test:(NSString *)info{
    NSLog( @"%@--%@",info,[NSThread currentThread]);
}

输出结果:
主队列[2018:730534] --><NSThread: 0x14d50c370>{number = 1, name = main}

添加block任务简略方式:

-(void)operationQueueAsynDemo2{
    //1 获取主队列
    NSOperationQueue *mainQueue=[NSOperationQueue mainQueue];
    //2 创建block任务
    NSBlockOperation *blockOperation=[NSBlockOperation blockOperationWithBlock:^{
        NSLog(@"-->%@",[NSThread currentThread]);
        
    }];
    //3 向队列中添加block任务
    [mainQueue addOperation:blockOperation];
}

** NSOperationQueue主队列总结:**
NSOperationQueue主队列不创建线程,并且异步方式执行,不然阻塞主线程。

并发队列

操作并发队列-NSInvationOperation类型任务

//并发队列 Invocation任务
-(void)operationQueueAsynDemo1 {
    
    //1 创建队列:冲过alloc init方式创建的队列为并发异步队列
    NSOperationQueue *concurrentQueue=[[NSOperationQueue alloc] init];
    //2 创建任务
    NSInvocationOperation *invocationOperation=[[NSInvocationOperation alloc] initWithTarget:self selector:@selector(invocationOperationSyn:) object:@"OperationQueue_syn"];
    //3 向队列中添加任务
    [concurrentQueue addOperation:invocationOperation];
}

-(void)invocationOperationSyn:(NSString *)info{
        NSLog(@"%@--%@",info,[NSThread currentThread]);
}

   

输出结果:
[2023:732400] --><NSThread: 0x134593e80>{number = 2, name = (null)}

并发队列-NSBlockOperation类型任务

//并发队列 block任务
-(void)operationQueueAsynDemo2{
    
    //1 创建并发对列
    NSOperationQueue *concurrentQueue=[[NSOperationQueue alloc] init];
    //2 创建block任务
    NSBlockOperation *blockOperation=[NSBlockOperation blockOperationWithBlock:^{
        NSLog( @"%@-->",[NSThread currentThread]);
    }];
    //3 向队列中添加任务
    [concurrentQueue addOperation:blockOperation];
}

-(void)invocationOperationSyn:(NSString *)info{
        NSLog(@"%@--%@",info,[NSThread currentThread]);
}

输出结果:
[2026:733095] <NSThread: 0x15cd9aac0>{number = 2, name = (null)}-->

添加block任务简略方式:

-(void ) operationQueueAsynDemo3{
    
    //1 创建并发队列
    NSOperationQueue *concurrent=[[NSOperationQueue alloc] init];
    //2 向队里中添加 blok
    [concurrent addOperationWithBlock:^{
        NSLog(@"%@",[NSThread currentThread]);
        
    }];
}

** NSOperationQueue并发队列总结:**
NSOperationQueue并发队列创建线程,并且异步方式执行

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

推荐阅读更多精彩内容