多线程
NSThread(OC)
一个NSThread对象就代表一条线程
开启子线程的方法:
1.NSThread * thread = [[NSThread alloc] initWithTarget:self selector:@selector(run) object:nil];
[thread start];
2.[NSThread detachNewThreadSelector:@selector(run) toTarget:self withObject:nil]; 创建完就启动
3.[self performSelectorInBackground:@selector(run:) withObject:@“abc参数”]; 隐式创建子线程
线程一启动就会在线程thread中执行self的run方法
NSThread * current = [NSThread currentThread]; 获得当前的线程
num=1 表示主线程 num!=1 表示子线程
线程的调度优先级
+ (double)threadPriority;
+ (BOOL)setThreadPriority:(double)p;
调度优先级的取值范围是0.0-1.0 默认是0.5 值越大优先级越高
线程的状态:
1.新建New
2.就绪Runnable [thread start];
3.运行Running
4.阻塞Blocked
1> [NSThread sleepForTimeInterval:5.0];
2> [NSDate dateWithTimeIntervalSinceNow:5.0];
[NSThread sleepUntilDate:date];
5.死亡Dead
[self.thread exit];
一旦线程死亡了 就不能再运行
多线程的安全隐患
(同步锁 互斥锁)
互斥锁使用格式:(需要消耗大量的CPU资源)(多条线程抢夺同一块资源)
// 开始加锁(锁代码块 必须是同一把锁 一般是self)
@synchronized(锁对象){
// 锁住的代码块(对成员变量的修改)
}
// 解锁
线程同步:多条线程按顺序的执行任务(互斥锁)
(atomic)原子属性: 会为setter方法加锁
(nonatomic)非原子属性: 不会为setter方法加锁
ios开发的建议:
1.所有属性都声明为nonatomic
2.尽量避免多线程抢夺同一块资源
3.尽量将加锁 资源抢夺的业务逻辑交给服务端处理 减小移动客户端的压力
线程间的通讯
1.1个线程传递数据给另一个线程
2.在一个线程中执行特定任务后 转到另一个线程继续执行任务
- (void)performSelectorOnMainThread:(SEL)aSelector withObject:(id)arg waitUntilDone:(BOOL)wait;
- (void)performSelector:(SEL)aSelector onThread:(NSThread *)the withObject:(id)arg waitUntilDone:(BOOL)wait;
【注意】
刷新UI界面必须在主线程
GCD(C)(Grand Central Dispatch)牛逼的中枢调度器
1.定制任务
2.将任务添加到队列中(先进先出 后进后出)
执行任务的函数:
同步的方式(在当前线程中执行)(不具备开启新新线程的能力 )
1.dispatch_sync(dispatch_queue_t queue, dispatch_block_t block);
queue:队列 block:任务
异步的方式(在另一条线程中执行)(具备开启新线程的能力)
2.dispatch_async(dispatch_queue_t queue, dispatch_block_t block);
队列:(决定了任务的执行方式)
1.并发队列
可以让多个任务并发(同时)执行(自动开启多个线程同时进行任务)
并发只有在异步(dispatch_async)函数下才有效
2.串行队列
让任务一个接着一个的执行(一个任务执行完毕之后 再执行下一个任务)
/**
* 用dispatch_sync同步函数往串行列中添加任务
*/
- (void)syncSerialQueue
{
// 1.创建串行队列
dispatch_queue_t queue = dispatch_queue_create("com.itheima.queue", NULL);
// 2.添加任务到队列中 执行
dispatch_sync(queue, ^{
NSLog(@"----