ios thread learn
- pThread
- NSThread
- GCD
- NSOperation
pThread
基于c++框架,多平台
// oc
pthread_t pthread;
NSLog(@"我在主线程中执行!");
phread_create(&pthread,NULL,run,NULL); // 创建线程
void *run(void *data){
NSLog(@"我在子线程中执行!");
return NULL;
}
从图中可以看出当前进程号及线程号。两个log方法在相同的进程中不同的线程下执行。
NSThread
// oc
// NSThread创建线程三种方法(三选一)
// 1.通过alloc init的方式创建线程执行线程)
NSLog(@"我在主线程中执行!");
NSThread *thread1 = [[NSThread alloc] initWithTarget:self selector:@selector(runThread) object:nil];
// 开始线程
[thread1 start];
// 2.通过detachNewThreadSelecor 方式创建线程
[NSThread detachNewThreadSelecor:@selector(runThread) toTarget:self withObject:nil];
// 3.通过performSelectorInBackground 方式创建线程
[self performSelectorInBackground:@selector(runThread) withObject:nil];
// 线程方法
-(void) runThread {
NSLog(@"我在子线程中执行!");
// 回到主线程执行
[self performSelectOnMainThread:@selector(runMainThread) withObject:nil waitUntilDone:YES];
}
// 主线程方法
-void runMainThread {
NSLog(@"回到主线程执行!");
}
第一种方式需要调用线程对象的start方法执行线程而其他两种直接开启线程。
// 第一种方法
// 设置线程名称
[thread1 setName:@"Name_Thread1"];
// 获得线程name
[NSThread currentThread].name;
// 优先级(double)
[thread1 setThreadPriority:0.5]
GCD
苹果提出的更加有效的利用多核CPU的技术,线程自动管理如:创建线程、任务调度、销毁线程等,使用更加方便和灵活。
简单使用方法
同步及异步任务:
串行及并行任务:
// dispatch_get_main_queue & dispatch_get_global_queue
// oc
-(void) clickGCD {
NSLog(@"执行GCD");
dispatch_async(dispatch_get_global_queue(0,0),^{
// 执行耗时任务(代码忽略)
NSLog(@"start task 1");
dispatch_async(dispatch_get_main_queue(),^{
// 回到主线程刷新UI
NSLog(@"刷新UI");
})
})
}
存储数据库及同步图片都可以采取此种方式。
// dispatch_get_global_queue是一个全局并发的queue
dispatch_async(dispatch_get_global_queue(0,0),^{
NSLog(@"start task 1");
[NSThread sleepForTimeInterval:2];
NSLog(@"end task 1");
});
dispatch_async(dispatch_get_global_queue(0,0),^{
NSLog(@"start task 2");
[NSThread sleepForTimeInterval:2];
NSLog(@"end task 2");
});
dispatch_async(dispatch_get_global_queue(0,0),^{
NSLog(@"start task 3");
[NSThread sleepForTimeInterval:2];
NSLog(@"end task 3");
});
// 设置线程优先级
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_LOW,0),^{
NSLog(@"start task 1");
[NSThread sleepForTimeInterval:2];
NSLog(@"end task 1");
});
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH,0),^{
NSLog(@"start task 1");
[NSThread sleepForTimeInterval:2];
NSLog(@"end task 1");
});
如果保证执行顺序,需要使用串行执行。
// 自定义queue
// DISPATCH_QUEUE_SERIAL == NULL
dispatch_queue_t queue = dispatch_queue_create("com.test.gcd.queue",NULL);
dipatch_async(queue,^{
NSLog(@"start task 1");
[NSThread sleepForTimeInterval:2];
NSLog(@"end task 1");
});
dipatch_async(queue,^{
NSLog(@"start task 2");
[NSThread sleepForTimeInterval:2];
NSLog(@"end task 2");
});
dipatch_async(queue,^{
NSLog(@"start task 3");
[NSThread sleepForTimeInterval:2];
NSLog(@"end task 3");
});
线程ID相同即上述代码单线程执行3个任务,没有实现多线程执行条件。
// 上段代码创建线程更换参数 DISPATCH_QUEUE_CONCURRENT
dispatch_queue_t queue = dispatch_queue_create("com.test.gcd.queue",DISPATCH_QUEUE_CONCURRENT);
线程ID不同即上述代码3个线程分别执行3个任务。
GCD_Group
多个任务异步处理的时候,有的时候需要告诉程序所有的任务已经执行完毕,当得知所有任务执行完成后会调用回调函数执行其他任务。
// 创建并行queue
dispatch_queue_t queue = dispatch_queue_t queue = dispatch_queue_create("com.test.gcd.group",DISPATCH_QUEUE_CONCURRENT);
dispatch_group_t group = dispatch_group_create();
dispatch_group_async(group,queue, ^{
NSLog(@"start task 1");
[NSThread sleepForTimeInterval:2];
NSLog(@"end task 1");
});
dispatch_group_async(group,queue, ^{
NSLog(@"start task 2");
[NSThread sleepForTimeInterval:2];
NSLog(@"end task 2");
});
dispatch_group_async(group,queue, ^{
NSLog(@"start task 3");
[NSThread sleepForTimeInterval:2];
NSLog(@"end task 3");
});
dispatch_group_notify(group,queue,^{
NSLog(@"All tasks over");
});
// 回到主线程执行回调
dispatch_group_notify(group,queue,^{
NSLog(@"All tasks over");
dispatch_async(
NSLog(@"回到主线程刷新UI");
});
});
回调最后一个线程task3所对应的线程,没有单独开辟一个线程去执行回调任务,如果希望回到主线程执行调用回到主线程所对应的方法。
// 异步请求 dispatch_group_enter 及 dipatch_group_leave 同时出现
dispatch_group_t group = dispatch_group_create();
dispatch_group_enter(group);
[self sendRequest:^{
NSLog(@"request done!")
dipatch_group_leave(group)
}]; <br> #### GCD 单例模式及延迟执行 #### **单例模式**
+ (instancetype) instance{
static dispatch_once_t onceToken;
static TestSingle *ins = nil;
dispatch_once(&onceToken,^{
NSLog(@"init the TestSingle")
ins = [[TestSingle alloc] init];
})
return ins;
}
// 使用
-(void)clickSingle {
TestSingle *single = [TestSingle instance];
NSLog(@"%@",single);
}
执行多次clickSingle方法后“init the TestSingle” 只执行一次,即单例模式执行完之后,如果不销毁一直会存在会内存中。
延迟执行
// 使用
NSLog(@"----begin----")
-(void)clickSingle {
// DISPATCH_TIME_NOW(当前时间) NSEC_PER_SEC(每秒) dispatch_get_main_queue(在主线程中执行)
dispatch_after(dispatch_time(DISPATCH_TIME_NOW,(int64_t)(2*NSEC_PER_SEC)),dispatch_get_main_queue(),^{
NSLog(@"delay excute");
})
}
弊端是方法一旦执行不能够取消掉。
NSOperation
NSOperation是GCD的一种封装,封装了实例执行的操作及数据,能够以并发或非并发的方式执行操作。
通过使用NSOperation子类来调用其内部的方法。
1.NSInvocationOperation & NSBlockOperation (自带方法)
2.自定义类继承NSOperation
NSInvocationOperation
// 非并发执行
-(void) operationTest {
NSInvocationOperation *invocationOper = [[NSInvocationOperation alloc] initWithTarget:self selector:@selector(invocationAction) object:nil];
[invocationOper start];
}
// 并发执行
-(void) operationTest {
NSLog(@"main thread");
dispatch_async(dispatch_get_global_queue(0,0),^{
NSInvocationOperation *invocationOper = [[NSInvocationOperation alloc] initWithTarget:self selector:@selector(invocationAction) object:nil];
[invocationOper start];
})
NSLog(@"end");
}
-(void) invocationAction {
for (int i=0;i<3;i++){
NSLog(@"invocation %d",i);
[NSTread sleepForTimeInterval:1];
}
}
非并发执行
并发执行
NSBlockOperation
-(void) operationTest {
NSLog(@"main thread");
dispatch_async(dispatch_get_global_queue(0,0),^{
NSBlockOperation *blockOper = [NSBlockOperation blockOperationWithBlock:^{
for (int i=0;i<3;i++){
NSLog(@"invocation %d",i);
[NSTread sleepForTimeInterval:1];
}
}];
[blockOper start];
})
}
相关概念:
NSOperationQueue 可以理解成线程池,创建线程后可以将线程添加至队列中。
a.addOperation // 添加至线程池
b.setMaxCouncurrentOperationCount // 设置最大并发数
// 创建NSOperationQueue
@property (nonatomic,strong) NSOperationQueue *operQueue;
if(!self.operQueue) {
self.operQueue = [[NSOperationQueue alloc] init];
}
// 上述代码创建的线程
[self.operQueue addOperation:blockOper];
状态
ready、cancelled、executing、finished、asynchronous
一旦线程执行无法cancelled,可以在代码内部判断
依赖-addDependency
// 创建NSOperationQueue
@property (nonatomic,strong) NSOperationQueue *operQueue;
NSBlockOperation *customOperA = [NSBlockOperation blockOperationWithBlock:^{
for (int i=0;i<3;i++){
NSLog(@"OperA %d",i);
[NSTread sleepForTimeInterval:1];
}
}];
NSBlockOperation *customOperB = [NSBlockOperation blockOperationWithBlock:^{
for (int i=0;i<3;i++){
NSLog(@"OperB %d",i);
[NSTread sleepForTimeInterval:1];
}
}];
NSBlockOperation *customOperC = [NSBlockOperation blockOperationWithBlock:^{
for (int i=0;i<3;i++){
NSLog(@"OperC %d",i);
[NSTread sleepForTimeInterval:1];
}
}];
NSBlockOperation *customOperD = [NSBlockOperation blockOperationWithBlock:^{
for (int i=0;i<3;i++){
NSLog(@"OperD %d",i);
[NSTread sleepForTimeInterval:1];
}
}];
// 不要循环依赖
[customOperD addDependency:customOperA];
[customOperA addDependency:customOperC];
[customOperC addDependency:customOperB];
// 添加线程池
[self.operQueue addOperation:customOperA];
[self.operQueue addOperation:customOperB];
[self.operQueue addOperation:customOperC];
[self.operQueue addOperation:customOperD];
线程锁
// synchronized oc
@synchronized(self) {
// 执行代码段
}
// NSCondition oc
@property (nonatomic,strong) NSCondition *condition
self.condition = [[NSCondition alloc] init];
[self.condition lock];
// 执行代码段
[self.condition unlock];