iOS开发随性总结之多线程

什么是多线程?

要知道什么是多线程首先要了解进程和线程的概念。

进程:

指系统中正在运行的应用程序,而且每个进程之间是相互独立的

线程:

程序执行的基本单元,程序中的任务都在线程中执行
线程中执行任务的方式分为串行和并行,串行指所有任务按照顺序依次执行,并行是指在一个线程中多个任务同时执行

多线程:

在一个进程中可以开辟多个线程来同时(并行)运行,每个线程也可串行或并行执行任务。但是CPU同一时间只能处理一条线程,多线程并发执行其实是由于CPU运行速度足够快,在多条线程之间进行调度,造成了多条线程并发执行的假象,如果有非常多的线程同时执行,也许会造成CPU崩溃
多线程的优缺点:

多线程的优缺点

优点:

①能适当提高程序的执行效率
②能适当提高资源利用率(CPU、内存利用率)

缺点:

①开启线程需要占用一定的内存空间(默认情况下,主线程占用1M,子线程占用512KB),如果开启大量的线程,会占用大量的内存空间,降低程序的性能
②线程越多,CPU在调度线程上的开销就越大
③程序设计更加复杂:比如线程之间的通信、多线程的数据共享

iOS里面实现多线程的方案:

#######iOS中目前多线程有4套实现方案:

Pthread:

这是一套在很多操作系统上都通用的多线程API,移植性很强。不过这是基于c语言的框架,使用起来有点困难,对程序猿的技术要求略高

NSThread:

是相对轻量级的,但也是使用起来最负责的,你需要自己管理thread的生命周期,线程之间的同步。线程共享同一应用程序的部分内存空间,它们拥有对数据相同的访问权限。

GCD:

Grand Central Dispatch (GCD)是Apple开发的一个多核编程的较新的解决方法。GCD是一个替代诸如NSThread等技术的很高效和强大的技术。GCD完全可以处理诸如数据锁定和资源泄漏等复杂的异步编程问题。GCD的工作原理是让一个程序,根据可用的处理资源,安排他们在任何可用的处理器核心上平行排队执行特定的任务。这个任务可以是一个功能或者一个程序段。这是iOS开发中最多使用的多线程实现方案

NSOperation:

NSOperation实际上是苹果对GCD的封装,相对于GCD来说可控性更高,NSOperation实际上是一个抽象的基类,并不能直接使用,需要通过继承于它的子类来调用各种方法实现功能

简单实现

pthread:

首先当然是导入头文件
<pre><code>

import "pThread"

</code></pre>

假设我们有一耗时操作(写成函数指针形式)

void *run(void *costTime) {
  for (NSInteger i = 0; i < 10000; i++) {   
    NSLog(@"%ld", i)
  }   
}

这里我是设置一个Button的点击事件来执行

- (void)btnClick {
  pthread_t pThread;
  pthread_create(&pthread, NULL, run, NULL);
  // 第一个参数:线程指针
  // 第二个参数:线程的一些属性    
  // 第三个参数:用于执行方法的函数指针
  // 第四个参数:线程中的传值
}

这样就创建了一条线程来执行函数costTime,主线程的任务可以继续执行,不必等待

NSThread:

- (void)creadNSThread
{
    // 创建线程
    NSThread *thread = [[NSThread alloc] initWithTarget:self selector:@selector(costTime) object:@"111"];
    thread.name = @"222";
    
    // 开启线程
    [thread start];
    NSLog(@"%@", [NSThread currentThread]);//当前线程
    NSLog(@"%@", [NSThread mainThread]);//主线程
    NSLog(@"%d", [NSThread isMainThread]);//是否为主线程
}
// 快捷创建方式
- (void)creatNSThread1
{
    // 快捷创建 无返回值
    [NSThread detachNewThreadSelector:@selector(costTime) toTarget:self withObject:nil];
}

NSOperation:

- (void)createNSOperation
{
    NSInvocationOperation *operation_1 = [[NSInvocationOperation alloc] initWithTarget:self selector:@selector(operationAction1) object:nil];
    NSInvocationOperation *operation_2 = [[NSInvocationOperation alloc] initWithTarget:self selector:@selector(operationAction2) object:nil];
    // block方式创建多线程
    NSBlockOperation *operation_3 = [NSBlockOperation blockOperationWithBlock:^{
        NSLog(@"第三个 -- %d", [NSThread isMainThread]);
        for (int i = 0; i < 1000; i++) {
            NSLog(@"第三个 -- %d", i);
        }
    }];
    
    // 操作队列
    // 目的:将任务放在一个队列中执行
    // 任务:任务执行在主线程还是在子线程全部都是由我们的队列来决定的
    // 获取主队列
//    NSOperationQueue *queue = [NSOperationQueue mainQueue];
    // alloc init 的代表字其他队列
    NSOperationQueue *queue = [[NSOperationQueue alloc] init];
    // 先加入队列的先执行,但是执行的时间不定,可能后执行的比先执行的先执行完
    [queue addOperation:operation_1];
    [queue addOperation:operation_2];
    [queue addOperation:operation_3];
    
}   

- (void)operationAction1
{
    NSLog(@"第一个 -- %d", [NSThread isMainThread]);
    for (int i = 0; i < 1000; i++) {
        NSLog(@"第一个 -- %d", i);
    }
}

- (void)operationAction2
{
    NSLog(@"第二个 -- %d", [NSThread isMainThread]);
    for (int i = 0; i < 1000; i++) {
        NSLog(@"第二个 -- %d", i);
    }
}

GCD:

- (void)viewDidLoad {
    [super viewDidLoad];
// 下面这种方式中,最内层的任务永远不会执行,因为任务2要等待任务执行完才会执行,而任务2又在任务1中,造成类似死循环
// 所以这里是一个错误演示
    dispatch_queue_t queue = dispatch_queue_create("sss", DISPATCH_QUEUE_CONCURRENT);
    dispatch_async(queue, ^{
        NSLog(@"1 --- %@", [NSThread currentThread]);
        dispatch_sync(queue, ^{
            NSLog(@"2 --- %@", [NSThread currentThread]);
        });
    });
}
实现:

根据GCD执行方式,可将其分为几种类型
根据线程执行方式分为同步:同一个线程顺序执行 异步:不在一个线程执行
根据任务执行方式串行:串在一起执行 并行:一起执行
主队列不会开辟新的线程,所以使用主线程执行任务只有同步串行一种方式

// 此处只实现异步并发方式
// 异步 + 并发队列 具备开启子线程的能力,并且并发执行任务
- (void)createAsyncConcurrent
{
    dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
    dispatch_async(queue, ^{
        NSLog(@"1 --- %@", [NSThread currentThread]);
    });
    dispatch_async(queue, ^{
        NSLog(@"2 -- %@", [NSThread currentThread]);
    });
    dispatch_async(queue, ^{
        NSLog(@"3 --- %@", [NSThread currentThread]);
    });
}

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

推荐阅读更多精彩内容