关于线程的小总结

为了方便测试,我们写一个耗时计算的方法:

-(void)calculateAction{

// 当子线程中出现对象类型时,需要使用自动释放池包裹对应的代码

@autoreleasepool {

int sum = 0;

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

sum += i;

}

// 打印当前方法是否为主线程

NSLog(@"===当前线程A:%d",[NSThread isMainThread]);

// 打印当前线程

NSLog(@"===当前线程B:%@",[NSThread currentThread]);

NSLog(@"===结果:%d",sum);

}

}


1、NSThread

NSThread的创建:

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

[thread start];

NSLog(@"===当前线程%d",[NSThread isMainThread]);

NSLog(@"===当前线程11:%@",[NSThread currentThread]);

[thread cancel];

这里,我们可以看到输出的结果是:耗时计算的方法是在子线程中执行。

关于线程的小总结_第1张图片

同时,NSThread还包含isExecuting、isCancelled属性,是否在执行,是否取消执行。NSThread需要手动开启。

[NSThread sleepForTimeInterval:10];关于这个方法的用处,在融云SDK里发送多张图片中用到过,在for循环中,加入延时执行代码,在发送效果上给人感觉是动态的,而不是直接生硬的瞬间出现多张图片的发送。

由于耗时计算是在子线程当中,当子线程中完成操作后,我们要回到主线程中去执行下一步操作,这里有两种回到主线程的方式:

1️⃣参数的意义:1、执行在主线程的方法 2、传递的参数 3、是否等待完成后操作

[self performSelectorOnMainThread:@selector(mainAction:) withObject:@(sum) waitUntilDone:YES];

-(void)mainAction:(NSNumber *)sum{

NSLog(@"计算的结果%d",[sum intValue]);

NSLog(@"当前线程是否为主线程:%d",[NSThread isMainThread]);

}

打印结果:

2️⃣

dispatch_async(dispatch_get_main_queue(), ^{

NSLog(@"===计算的结果%d",sum);

NSLog(@"===当前线程是否为主线程:%d",[NSThread isMainThread]);

});

静态方法直接开辟子线程:

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

2、NSObject

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

3、NSOperationQuene

NSOperationQuene:此种多线程方式和NSOperation的两个子类来结合使用实现多线程方式

// 3.1

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

// 3.2

NSBlockOperation *block = [NSBlockOperation blockOperationWithBlock:^{

[self test];

}];

// 创建管理队列的两个任务

NSOperationQueue *queue = [NSOperationQueue new];

// 设置最大并发数(同时执行的任务个数)

// 若最大并发数设置为1.那么任务按照串行方式执行(1就是跟串联一样)

[queue setMaxConcurrentOperationCount:2];

// 将任务添加到队列

[queue addOperation:invocation];

[queue addOperation:block];

一个检测先后顺序的test方法

-(void)test{

NSLog(@"测试的时间。。。。");

}

那么,最后输出的结果是:

关于线程的小总结_第2张图片

可以得出的结论是:队列中先加入谁就先执行谁,但是不代表先执行的方法就先结束。

4、GCD

两种队列方式:并行队列,串行队列

并行队列:所有任务并发执行,不分先后

串行队列:所有任务一次执行,排队完成

GCD中,有三种队列可以使用

主队列:系统提供的单例,属于串行队列

全局队列:系统提供的单例,属于并行队列

自定义队列:开发人员可以自定义选择使用串行或并行

主队列

关于线程的小总结_第3张图片

输出结果是:为顺序执行的串行队列

全局队列:并行队列(也遵循FIFO,先进先出原则)---会开辟子线程,但是其管理的任务不一定只在子线程执行,也会添加到主线程执行

// 1、队列优先级

// 2、空余参数,以后添加作用

dispatch_queue_t globalQueue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);

// 必须先执行的代码(第一个加入队列时,才会优先执行此任务)

dispatch_barrier_sync(globalQueue, ^{

NSLog(@"优先执行的代码");

});

dispatch_async(globalQueue, ^{

NSLog(@"第一个任务:%d",[NSThread isMainThread]);

});

dispatch_async(globalQueue, ^{

NSLog(@"第二个任务:%d",[NSThread isMainThread]);

});

dispatch_async(globalQueue, ^{

NSLog(@"第三个任务:%d",[NSThread isMainThread]);

});

// 延时启动任务

dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(2 * NSEC_PER_SEC)), globalQueue, ^{

NSLog(@"出来吧,神龙!");

});

// 反复执行n次的任务

dispatch_apply(3, globalQueue, ^(size_t time) {

NSLog(@"第%zu次",time);

});

// 添加函数

//  参数:1、要把任务添加到的队列 2、函数的参数 3、函数

dispatch_async_f(globalQueue, "I love my iOS teacher", function);

// 函数

void function(void * string);

void function(void * string){

NSLog(@"%s",string);

}

输出结果:

由此可以看出,第一到第三个任务并不是顺序执行的。为并行执行。

关于线程的小总结_第4张图片

自定义队列

串行

关于线程的小总结_第5张图片

当全部为sync时,线程顺序执行,优先在当前线程中执行,打印结果是:

当为async时,线程并行执行

关于线程的小总结_第6张图片

并行队列,当前线程为并行执行,且在用async,即异步的时候,是在子线程中执行

关于线程的小总结_第7张图片

串行但异步执行

关于线程的小总结_第8张图片

并行但异步执行

关于线程的小总结_第9张图片

分组:异步执行

关于线程的小总结_第10张图片

对线程的一些小总结,很简单,后续进行深入补充。

你可能感兴趣的:(关于线程的小总结)