您的位置:首页 > 移动开发 > IOS开发

iOS开发 多线程和GCD

2016-01-08 10:43 441 查看
多线程

多线程的三种方式:1.thread 2.OPerationQuete 3.NSObject

多线程:程序:有源代码生成可执行应用(.exe,.app)

进程:一个正在运行的程序可以看做是一个进程,进程拥有独立运行所需的全部资源

线程:多线程是为了系统可以运行多个程序,多线程是为了app可以运行多个任务

进程拥有独立的资源,线程不会

一个程序有一个或多个线程组成,进程只负责资源的调度,线程才是程序真正执行单元,负责代码执行

一个程序至少有一个线程,称为主线程,程序中只有一个主线程的程序,叫单线程程序;运行中会有多个线程的程序,叫多线程程序

子线程:iOS中允许用户开辟新线程,相对于主线程来说这些都是子线程

主线程:负责界面展现和刷新,旧版网络请求,数据库的请求,这些代码只能顺序执行,不能并发执行,

多线程的原理:CPU只能处理一条线程,只有一个线程在工作执行,多线程并发同时执行,其实就是CPU在多条线程之间调度切换,如果CPU调度线程的时间足够快,就造成多条线程并发执行的假象

思考:如果线程非常非常多,会发生什么情况?

CPU会在N多线程之间调度,CPU会累死,消耗大量的CPU资源

每条线程被调度执行的频次会降低(线程的执行效率降低)

3.多线程的优缺点

多线程的优点

能适当提高程序的执行效率

能适当提高资源利用率(CPU、内存利用率)

多线程的缺点

开启线程需要占用一定的内存空间(默认情况下,主线程占用1M,子线程占用512KB),如果开启大量的线程,会占用大量的内存空间,降低程序的性能

线程越多,CPU在调度线程上的开销就越大

程序设计更加复杂:比如线程之间的通信、多线程的数据共享

4.多线程在iOS开发中的应用

主线程:一个iOS程序运行后,默认会开启1条线程,称为“主线程”或“UI线程”

主线程的主要作用

1. 显示\刷新UI界面

2. 处理UI事件(比如点击事件、滚动事件、拖拽事件等)

3.主线程的使用注意:别将比较耗时的操作放到主线程中。

4. 耗时操作会卡住主线程,严重影响UI的流畅度,给用户一种“卡”的坏体验

在storyboard中添加一个按钮,再拖拽点击事件

#import "ViewController.h"

@interface ViewController ()

@end

@implementation ViewController

- (void)viewDidLoad {

[super viewDidLoad];

}

#pragma mark thread方式;

- (IBAction)CountAction:(id)sender {

/*

//开启多线程

//方式一:需要手动在合适时机开启线程

NSThread *thread = [[NSThread alloc] initWithTarget:self selector:@selector(threadAction) object:nil];

thread.name = @"text";

//手动开启;

[thread start];

//方式二:直接就开启线程,不需要手动启动

//[NSThread detachNewThreadSelector:@selector(threadAction) toTarget:self withObject:nil];

NSLog(@"%@",[NSThread currentThread]);

*/

#pragma mark NSOperationQueue;

/*

NSOperationQueue:操作队列

会根据操作的数量分配合适的线程去进行操作,通常与NSOperation进行配合操作,用户可以不用关心多线程,只需将每个多线程的任务做成NSOperation,然后放到队列中。队列会自动创建合适的线程

NSOperation:操作

NSOperation:本身并没有子线程,只是一个操作,多线程的是Queue

NSOperation:是一个抽象类,不能直接使用,一般是使用他的子类NSBlockOperation,NSInvocationOperation

*/

/*

//创建操作

NSInvocationOperation *op1 =[[NSInvocationOperation alloc] initWithTarget:self selector:@selector(invocationAction) object:nil];

//

//[op1 start];

//创建操作

NSBlockOperation *op2 = [NSBlockOperation blockOperationWithBlock:^{

NSLog(@"block:%@",[NSThread currentThread]);

// [op2 start];

} ];

// NSBlockOperation *op3 = [NSBlockOperation blockOperationWithBlock:^{

// NSLog(@"block2:%@",[NSThread currentThread]);

// }];

//

// NSBlockOperation *op4 = [NSBlockOperation blockOperationWithBlock:^{

// NSLog(@"block3:%@",[NSThread currentThread]);

// }];

//

//创建操作队列

NSOperationQueue *queue = [[NSOperationQueue alloc] init];

//每个操作可以设置优先级

op1.queuePriority = NSOperationQueuePriorityHigh;

//queue可以设置最大并行线程数

//当最大线程数设置为1的时候,是串行(可以保证任务是串行的)但是不能保证线程好使一样的

queue.maxConcurrentOperationCount = 3;

[op1 addDependency:op2];//添加依赖,当第二个执行结束的时候

[queue addOperation:op1];

[queue addOperation:op2];

// [queue addOperation:op3];

// [queue addOperation:op4];

*/

#pragma mark NSObject

[self performSelectorInBackground:@selector(threadAction) withObject:nil];

NSLog(@"%@",[NSThread currentThread]);

}

//NSOperationQueue;的点击事件

- (void)invocationAction{

NSLog(@"invocation:%@",[NSThread currentThread]);

}

- (void)threadAction{

//输出1-1000000

for (int i = 0; i < 1000000; i++) {

// NSLog(@"%d",i);

}

NSLog(@"%@",[NSThread currentThread]);

}

@end

GCD

全称:Grand Central Dispatch :是苹果公司开发的,以优化应用程序支持多核和其他对称多系统的系统

GCD是函数级编程,所以更高效,功能更强大

任务:

具有一定功能的代码段,一般是一个Block或者函数

分发队列:

GCD以队列的方式进行工作,FIFO(先进先出)。

GCD会根据分发队列的不同,创建合适数量的线程执行队列中的任务

队列两种:

一种是串行队列:1.系统提供的串行队列 2.自定义串行队列

一种是并行队列:1.系统提供的串行队列 2.自定义串行队列



在storyboard中建立几个button,并拖拽点击事件

//采用系统方式添加串行任务

- (IBAction)SerialMainAction:(id)sender {

//系统提供的串行队列其实就是主线程队列

//1.拿到主线程队列

dispatch_queue_t main = dispatch_get_main_queue();

//2.给主线程队列添加任务

dispatch_async(main, ^{

NSLog(@"我是主线程队列第1个任务%@",[NSThread currentThread]);

});

dispatch_async(main, ^{

NSLog(@"我是主线程队列第2个任务%@",[NSThread currentThread]);

});

dispatch_async(main, ^{

NSLog(@"我是主线程队列第3个任务%@",[NSThread currentThread]);

});

dispatch_async(main, ^{

NSLog(@"我是主线程队列第4个任务%@",[NSThread currentThread]);

});

dispatch_async(main, ^{

NSLog(@"我是主线程队列第5个任务%@",[NSThread currentThread]);

});

}

//采用自定义的方式添加串行任务

- (IBAction)SerialBySelfAction:(id)sender {

//创建串行队列

dispatch_queue_t serialQueue = dispatch_queue_create("yan5", DISPATCH_QUEUE_SERIAL);

//添加任务

dispatch_async(serialQueue, ^{

NSLog(@"自定义串行任务第一个%@",[NSThread currentThread]);

});

dispatch_async(serialQueue, ^{

NSLog(@"自定义串行任务第二个%@",[NSThread currentThread]);

});

dispatch_async(serialQueue, ^{

NSLog(@"自定义串行任务第三个%@",[NSThread currentThread]);

});

dispatch_async(serialQueue, ^{

NSLog(@"自定义串行任务第四个%@",[NSThread currentThread]);

});

dispatch_async(serialQueue, ^{

NSLog(@"自定义串行任务第五个%@",[NSThread currentThread]);

});

}

//通过系统方式创建并行队列

- (IBAction)GlobalAction:(id)sender {

//拿到并行队列

dispatch_queue_t globle = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);

//添加任务

dispatch_async(globle, ^{

NSLog(@"系统并行的第一个任务:%@",[NSThread currentThread]);

});

dispatch_async(globle, ^{

NSLog(@"系统并行的第二个任务:%@",[NSThread currentThread]);

});

dispatch_async(globle, ^{

NSLog(@"系统并行的第三个任务:%@",[NSThread currentThread]);

});

dispatch_async(globle, ^{

NSLog(@"系统并行的第四个任务:%@",[NSThread currentThread]);

});

dispatch_async(globle, ^{

NSLog(@"系统并行的第五个任务:%@",[NSThread currentThread]);

});

}

//自定义方式创建并行队列

- (IBAction)ConcurrentAction:(id)sender {

//拿到并行队列

dispatch_queue_t concurrent = dispatch_queue_create("1146", DISPATCH_QUEUE_CONCURRENT);

dispatch_async(concurrent, ^{

NSLog(@"自定义并行队列第一个任务:%@",[NSThread currentThread]);

});

dispatch_async(concurrent, ^{

NSLog(@"自定义并行队列第二个任务:%@",[NSThread currentThread]);

});

dispatch_async(concurrent, ^{

NSLog(@"自定义并行队列第三个任务:%@",[NSThread currentThread]);

});

dispatch_async(concurrent, ^{

NSLog(@"自定义并行队列第四个任务:%@",[NSThread currentThread]);

});

dispatch_async(concurrent, ^{

NSLog(@"自定义并行队列第五个任务:%@",[NSThread currentThread]);

});

}

//让任务延迟一段时间执行

- (IBAction)DelayAction:(id)sender {

double time = 6;

//第一个参数从什么时候开始延迟

//第二个参数延迟多长时间

dispatch_time_t DTime = dispatch_time(DISPATCH_TIME_NOW, time * NSEC_PER_SEC);

//拿到队列

dispatch_queue_t global = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);//拿到全局队列

//添加延时任务

dispatch_after(DTime, global, ^{

NSLog(@"我被执行");

});

}

//重复执行一个任务

//重复执行任务只能跟串行一起用

- (IBAction)RepeatAction:(id)sender {

//拿到全局队列

dispatch_queue_t globel = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);

NSArray *arr = @[@"阿猫",@"阿狗",@"阿彪"];

//添加重复任务

//1参数重复多少次2参数放在哪一个队列里 3参数任务的Block块

dispatch_apply(arr.count, globel, ^(size_t size) {

NSLog(@"arr[%zu]:%@",size,arr[size]);

});

}

// 让线程在程序运行期间只运行一次

- (IBAction)OnlyYouAction:(id)sender {

//创建一个静态的进程

static dispatch_once_t once;

dispatch_once(&once, ^{

NSLog(@"一次就好");

});

}

//线程之间的通信

/*

1.子线程中使用主线程的数据

2.主线程中使用子线程的数据

*/
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: