多线程
1.程序是一个可执行文件
2.进程是程序执行的一个操作实体
3.进程是线程的集合
4.多线程就是在一个程序(一个进程)中开启多条线路,为并发执行多个任务提供方便.
什么是线程?
1.进程当中并发执行的代码片段
2.线程是提高代码效率的一个手段
3.IOS中主要用于防止界面假死
4.线程是处理异步任务的主要手段
NSThread
优点:NSThread 比其他两个轻量级
缺点:需要自己管理线程的生命周期,线程同步。线程同步对数据的加锁会有一定的系统开销
1.+ (void)detachNewThreadSelector:(SEL)selector toTarget:(id)target withObject:(id)argument;
作用:开启并且执行一个线程
2.- (instancetype)initWithTarget:(id)target selector:(SEL)selector object:(id)argument
作用:创建一个线程但是不会执行,需要手动调用
3.NSThreadWillExitNotification
作用:通过通知中心监听此消息达到监听线程结束的目的
4.NSlock
作用:线程锁
5.如何取消NSThread
NSOperation
优点:不需要关心线程管理, 数据同步的事情,可以把精力放在自己需要执行的操作上。
1. NSOperation本身不是线程,它是一个线程操作
2.它常用的子类
1)NSInvocationOperation 通过方法指定线程要执行的任务
2)NSBlockOperation 通过block指定要执行的任务
3)可以继承NSOperation,然后重写main函数达到自定义任务的效果
3.NSOperationQueue 线程池,管理线程
可以设置最大开启的线程数 maxConcurrentOperationCount
如果设置为1,则成为串行队列,否则,为并发队列
GCD
GCD会自动根据任务在多核处理器上分配资源,优化程序。
1.什么是GCD
GCD 是苹果iOS4.0之后和block一起出现的技术,是苹果封装的更底层(c)更高效的多线程处理技术,GCD (grand-central-dispatch)是目前使用的最普遍的多线程处理技术,因为高效、简洁、实用
2.GCD的队列类型
1).主线程队列 dispatch_get_main_queue()
技术分享
2).子线程队列 dispatch_get_global_queue(0, 0)
技术分享
3.一次性执行(类似线程锁) static dispatch_once_t onceToken
Singleton为自定义的一个继承NSObject的类,时机应用中需要什么类型就写什么类型
技术分享
4.延时执行 dispatch_time_t ,dispatch_after
5.自定义队列dispatch_queue_create
技术分享
注意:自定义队列只开启一条线程,执行多个任务时为串行队列
6.分组合并dispatch_group_create
技术分享
7.dispatch_group_async
可以实现监听一组任务是否完成,完成后得到通知执行其他的操作
dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
dispatch_group_t group = dispatch_group_create();
dispatch_group_async(group, queue, ^{
[NSThread sleepForTimeInterval:1];
NSLog(@"group1");
});
dispatch_group_async(group, queue, ^{
[NSThread sleepForTimeInterval:2];
NSLog(@"group2");
});
dispatch_group_async(group, queue, ^{
[NSThread sleepForTimeInterval:3];
NSLog(@"group3");
});
dispatch_group_notify(group, dispatch_get_main_queue(), ^{
NSLog(@"updateUi");
});
dispatch_release(group);
8.dispatch_barrier_async
是在前面的任务执行结束后它才执行,而且它后面的任务等它执行完成之后才会执行
dispatch_queue_t queue = dispatch_queue_create("gcdtest.rongfzh.yc", DISPATCH_QUEUE_CONCURRENT);
dispatch_async(queue, ^{
[NSThread sleepForTimeInterval:2];
NSLog(@"dispatch_async1");
});
dispatch_async(queue, ^{
[NSThread sleepForTimeInterval:4];
NSLog(@"dispatch_async2");
});
dispatch_barrier_async(queue, ^{
NSLog(@"dispatch_barrier_async");
[NSThread sleepForTimeInterval:4];
});
dispatch_async(queue, ^{
[NSThread sleepForTimeInterval:1];
NSLog(@"dispatch_async3");
});
9.dispatch_apply
执行某个代码片段N次。
dispatch_apply(5, globalQ, ^(size_t index) {
// 执行5次
});
四.线程间通信
线程间通信和进程间通信从本质上讲是相似的。线程间通信就是在进程内的两个执行流之间进行数据的传递,就像两条并行的河流之间挖出了一道单向流动长沟,使得一条河流中的水可以流入另一条河流,物质得到了传递。
1.performSelect On The Thread
框架为我们提供了强制在某个线程中执行方法的途径,如果两个非主线程的线程需要相互间通信,可以先将自己的当前线程对象注册到某个全局的对象中去, 这样相 互之间就可以获取对方的线程对象,然后就可以使用下面的方法进行线程间的通信了,由于主线程比较特殊,所以框架直接提供了在出线程执行的方法。
@interface NSObject (NSThreadPerformAdditions)
- (void)performSelectorOnMainThread:(SEL)aSelector withObject:(id)arg waitUnti
2.Mach Port
在苹果的Thread Programming Guide的Run Pool一节的Configuring a Port-Based Input Source 这一段中就有使用Mach Port进行线程间通信的例子。 其实质就是父线程创建一个NSMachPort对象,在创建子线程的时候以参数的方式将其传递给子线程,这样子线程中就可以向这个传过来的 NSMachPort对象发送消息,如果想让父线程也可以向子线程发消息的话,那么子线程可以先向父线程发个特殊的消息,传过来的是自己创建的另一个 NSMachPort对象,这样父线程便持有了子线程创建的port对象了,可以向这个子线程的port对象发送消息了。
当然各自的port对象需要设置delegate以及schdule到自己所在线程的RunLoop中,这样来了消息之后,处理port消息的delegate方法会被调用,你就可以自己处理消息了。