ios多线程方案由以下几种,目前官方推荐使用NSOperation,和java一样有线程池ThreadPool的概念,ios线程池就是NSOperationQueue。
NSOperation使用步骤如下:
下面给出demo,NSOperation是个抽象类,NSInvocationOperation 和NSBlockOperation是它的子类,demo会介绍这种子类的用法以及配合NSOperationQueue一起使用实现多线程。同时介绍线程的启动,暂停,继续,取消。
//
// ThreadViewController.m
// study2024
//
// Created by zhifei zhu on 2024/8/17.
//
#import "ThreadViewController.h"
@interface ThreadViewController ()
- (IBAction)mainQueue:(id)sender;
@property (weak, nonatomic) IBOutlet UIButton *mainQueueBtn;
- (IBAction)NSInvocationOperationTest:(id)sender;
- (IBAction)NSBlockOperationTest:(id)sender;
- (IBAction)NSOperationQueueStart:(id)sender;
- (IBAction)NSOperationQueuePause:(id)sender;
- (IBAction)NSOperationQueueContinue:(id)sender;
- (IBAction)NSOperationQueueConcel:(id)sender;
@property NSOperationQueue *queue;
@end
@implementation ThreadViewController
//懒加载queue属性
-(NSOperationQueue *)queue{
if(_queue==nil){
_queue=[[NSOperationQueue alloc]init];
_queue.maxConcurrentOperationCount=5;//设置队列最大并发数,不是线程总数,一般用2n+1 n代表cpu核数
}
return _queue;
}
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view from its nib.
}
/*
#pragma mark - Navigation
// In a storyboard-based application, you will often want to do a little preparation before navigation
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {
// Get the new view controller using [segue destinationViewController].
// Pass the selected object to the new view controller.
}
*/
//1.测试NSInvocationOperation继承至NSOperation
- (IBAction)NSInvocationOperationTest:(id)sender {
NSInvocationOperation *nsInvocationOperation=[[NSInvocationOperation alloc]initWithTarget:self selector:@selector(operationTest) object:nil];
[nsInvocationOperation setCompletionBlock:^{
NSLog(@"hello nsInvocationOperation is completion %@",[NSThread currentThread]);
}];
//直接start不会新建线程,还是运行在main主线程
// [nsInvocationOperation start];
//加入队列,会新起线程
NSOperationQueue *nsOperationQueue=[[NSOperationQueue alloc]init];
[nsOperationQueue addOperation:nsInvocationOperation];
}
- (void) operationTest{
NSLog(@"hello NSInvocationOperationTest %@",[NSThread currentThread]);
}
//2.测试NSBlockOperation继承至NSOperation
- (IBAction)NSBlockOperationTest:(id)sender {
NSBlockOperation *nsBlockOperation=[NSBlockOperation blockOperationWithBlock:^{
NSLog(@"hello NSBlockOperation %@",[NSThread currentThread]);
}];
[nsBlockOperation setCompletionBlock:^{
NSLog(@"hello NSBlockOperation is completion %@",[NSThread currentThread]);
}];
//直接start不会新建线程,还是运行在main主线程
// [nsBlockOperation start];
//加入队列,会新起线程
NSOperationQueue *nsOperationQueue=[[NSOperationQueue alloc]init];
[nsOperationQueue addOperation:nsBlockOperation];
}
//3.测试主队列,回到主队列就可以做线程间数据通信了
- (IBAction)mainQueue:(id)sender {
//添加NSBlockOperation到当前queue
[self.queue addOperationWithBlock:^{
NSLog(@"下载完成,当前队列%@",[NSOperationQueue currentQueue]);
}];
//获取主队列
[ [NSOperationQueue mainQueue]addOperationWithBlock:^{
NSLog(@"回到主队列,主线程,这里可以更新UI,当前队列%@,当前线程%@",[NSOperationQueue currentQueue],[NSThread mainThread]);
//更新按钮文字颜色为红色
[self.mainQueueBtn setTitleColor:[UIColor redColor] forState:UIControlStateNormal];
}];
}
//4.测试线程队列所有线程开始执行
- (IBAction)NSOperationQueueStart:(id)sender {
for(int a=0;a<20;a++){
[self.queue addOperationWithBlock:^{
//_queue.maxConcurrentOperationCount=2;//设置队列最大并发数,不是线程总数 不设置并发数,会每次都新创建一个
[NSThread sleepForTimeInterval:3];//睡眠3秒
NSLog(@"%d线程执行完成,当前线程%@",a,[NSThread currentThread]);
}];
}
}
//5.测试线程队列所有线程暂停
- (IBAction)NSOperationQueuePause:(id)sender {
[self.queue setSuspended:YES];
NSLog(@"暂停,当前线程数%lu",self.queue.operationCount);
}
//6.测试线程队列所有线程继续执行
- (IBAction)NSOperationQueueContinue:(id)sender {
[self.queue setSuspended:NO];
NSLog(@"继续,当前线程数%lu",self.queue.operationCount);
}
//7.测试线程队列所有线程取消
- (IBAction)NSOperationQueueConcel:(id)sender {
[self.queue cancelAllOperations];
NSLog(@"取消所有线程,当前线程数%lu",self.queue.operationCount);
}
@end