您的位置:首页 > 产品设计 > UI/UE

iOS多线程,NSThread ,NSOperationQueue ,GCD

2015-02-26 10:06 405 查看

iOS 多线程

1、进程跟线程

进程:
一个程序至少有一个进程,一个进程至少有一个线程、
有独立的内存空间、
同一个进程中的线程,共享内存中的内存跟资源、
进程相当与一个静态容器,里面装了很多活动的线程。
线程:
每一个程序都有一个主线程,程序启动的时候创建(调用main
来启动)、
主线程的生命周前,和应用程序是绑定的,程序退出时候,主线程也就停止了、

多线程,一个应用程序有多个线程,提高cpu的使用律,防止主线程堵塞、
任何有可能堵塞主线程的的任务都不要再主线程执行(比如网络请求)。

进程跟线程:我觉得这样更好理解,进程就好比我们的道路(道路相当于进程),如果只有一个车道(车道相当于线程),车流量一多,就可能会造成道路的堵塞,万一前面哪辆车碰撞了。整个道路就瘫痪堵塞了。这样子话,我们就可以开辟多个车道(线程)来缓解、加速,交通状况。当然。如果车道(线程)增多就会增加资源的耗用。这也就是多线程会损耗一定的资源。一个道路可以开辟多个车道,(一个进程,里面可以有多个线程);
ps:个人理解,欢迎纠正


2、iOS 多线程多种实现:

2.1、NSThread

//
------------------多线程第1种方式
NSThread *thread = [[NSThreadalloc]initWithTarget:self selector:@selector(thread) object:nil];

[thread start];

// ------------------多线程第2种方式

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

// ------------------多线程第3种方式

[self performSelectorInBackground:@selector(thread) withObject:nil];
//回到主线程

[self performSelectorOnMainThread:@selector(thread) withObject:nil waitUntilDone:NO];
NSlog(@"1111");

waitUntilDone 等待上面方法执行后再执行下面的内容,例如:如果waitUntilDone为yes,则等待方法执行完再打印111,如果为no,就执行方法,与打印111,同步执行!

2.2、NSOperationQueue

NSOperation 是一个抽象类,用来封装一个独立任务的代码与数据。不能直接使用该类,通过子类化或系统提供的子类来完成任务,NSOperationQueue是其系统提供的子类。
NSOperationQueue 用来管理operation 集合,决定他们的执行顺序,当一个 operation 被添加到queue后,一旦有多余的线程来执行这个 operation 。那么这个 operation 就会马上被执行。

// -------------------多线程第4种方式
//直接代码块方式实现
NSOperationQueue *operationQ =[[NSOperationQueue alloc]init];
[operationQ addOperationWithBlock:^{

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

NSLog(@"线程1111:%d",i);

} }];

// ------------------多线程第5种方式

//创建线程队列(线程池)

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

//线程的最大并发数,(如果有五个任务,并发为2的话,就是先执行前面两个,前面两个执行完一个才会轮到后面的任务执行)

operationQ.maxConcurrentOperationCount = 2;

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

//线程的优先级

[inOperation setQueuePriority:NSOperationQueuePriorityVeryLow];

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

//线程的优先级
[inOperation2 setQueuePriority:NSOperationQueuePriorityHigh];

//如果并发数是1得话、先添加进来的先执行

[operationQ addOperation:inOperation];
[operationQ addOperation:inOperation2];

2.3、GCD(Grand central dispatch) 一个纯 c 语言 写的库,

GCD 的优点:

在多核的硬件上,性能更佳!
并且操作简单,程序猿只需要告诉GCD
你要执行什么任务。不需要编写任何线程管理的代码;

如何用?

用之前先了解:

GCD 的两个核心的概念:

1、任务:执行什么样的操作

2、队列:用来存放任务的。

任务

1、同步,第一个参数要求我们放入一个队列,第二个参数就是我们要做的任务

dispatch_sync(<#dispatch_queue_tqueue#>, <#^(void)block#>)

2、异步

dispatch_async(<#dispatch_queue_tqueue#>, <#^(void)block#>)

.同步和异步的区别

同步:在当前线程中执行

异步:在另一条线程中执行

队列

1、并发队列(Concurrent Dispatch Queue),多个任务同时执行

dispatch_queue_t queue =dispatch_get_global_queue(<#long identifier#>, <#unsigned longflags#>)

2、串行队列(Serial Dispatch Queue),前一个任务执行完了,在执行下一个任务

dispatch_queue_create(<#const char *label#>,<#dispatch_queue_attr_t attr#>)

NSLog(@"主线程:%@",[NSThread
mainThread]);
/*
//(1)将异步执行,放入并发队列中
dispatch_queue_t queue =dispatch_get_global_queue(0, 0);
dispatch_async(queue, ^{
NSLog(@"11111 ===== >%@",[NSThread currentThread]);
});
dispatch_async(queue, ^{
NSLog(@"22222 ===== >%@",[NSThread currentThread]);
});
dispatch_async(queue, ^{
NSLog(@"33333 ===== >%@",[NSThread currentThread]);
});
//总结:开辟三个新线程
*/
/*
//(2)将异步执行,放入串行队列中
dispatch_queue_t queue =dispatch_queue_create("test", NULL);
dispatch_async(queue, ^{
NSLog(@"11111 ===== >%@",[NSThread currentThread]);
});
dispatch_async(queue, ^{
NSLog(@"22222 ===== > %@",[NSThreadcurrentThread]);
});
dispatch_async(queue, ^{
NSLog(@"33333 ===== >%@",[NSThread currentThread]);
});
//总结:会开启线程,但是只开启一个线程
*/

/*
//(3)将同步执行,放入串行队列中
dispatch_queue_t queue =dispatch_queue_create("test", NULL);
dispatch_sync(queue, ^{
NSLog(@"11111 ===== >%@",[NSThread currentThread]);
});
dispatch_sync(queue, ^{
NSLog(@"22222 ===== >%@",[NSThread currentThread]);
});
dispatch_sync(queue, ^{
NSLog(@"33333 ===== >%@",[NSThread currentThread]);
});
//总结:不会开辟新线程
*/
//(3)将同步执行,放入并发队列中
dispatch_queue_t queue =
dispatch_get_global_queue(0,
0);
dispatch_sync(queue, ^{
NSLog(@"11111 ===== >%@",[NSThread
currentThread]);
});
dispatch_sync(queue, ^{
NSLog(@"22222 ===== >%@",[NSThread
currentThread]);
});
dispatch_sync(queue, ^{
NSLog(@"33333 ===== >%@",[NSThread
currentThread]);
});

dispatch_async(dispatch_get_main_queue(), ^{

//回到主线程

});

};
//总结:不会开辟新线程,并发都失效了。。
(6)小结

说明:同步函数不具备开启线程的能力,无论是什么队列都不会开启线程;异步函数具备开启线程的能力,开启几条线程由队列决定(串行队列只会开启一条新的线程,并发队列会开启多条线程)。

同步函数

(1)并发队列:不会开线程

(2)串行队列:不会开线程

异步函数

(1)并发队列:能开启N条线程

(2)串行队列:开启1条线程

3、总结:

在开发中要注意:

当你启动新线程去执行某个任务的时候(比如,做网络请求),最终请求结束后,要回到主线程去更新ui。
回到主线程的方式”

1、
//回到主线程
[self performSelectorOnMainThread:@selector(thread) withObject:nil waitUntilDone:NO];
NSlog(@"1111");
waitUntilDone 等待上面方法执行后再执行下面的内容,例如:如果waitUntilDone为yes,则等待方法执行完再打印111,如果为no,就执行方法,与打印111,同步执行!

2、

dispatch_async(dispatch_get_main_queue(), ^{

//回到主线程
});

感谢纠正!

ps:每天进步一点点,做一个快乐的程序猿!
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: