学士学位网站重置密码怎么做,热狗seo优化外包,企业为什么要审计,wordpress读取相册1、多线程简介#xff1a;用户使用APP的时候如果每个操作都会等待好长的时间#xff0c;才能得到程序的响应#xff0c;这就影响了用户体验#xff0c;为了减少用户的等待时间#xff0c;我们可以使用多线程#xff1a;开辟出子线程去处理一些比较耗时的操作#xff08;…1、多线程简介用户使用APP的时候如果每个操作都会等待好长的时间才能得到程序的响应这就影响了用户体验为了减少用户的等待时间我们可以使用多线程开辟出子线程去处理一些比较耗时的操作例如加载数据这样减少了用户的等待时间提升了用户体验但是开辟线程会占用一定的内存主线程所占内存大小是1M子线程所占内存大小都是512KB并且该值不能通过编译器开关或线程API函数来更改降低程序的性能。所以一般情况下不要同时开辟过多线程。 2、使用多线程可能会出现的几个问题多个线程同时访问共享的数据发生Critical Section、Race Condition一个进程中多个线程之间的来回切换Context Switch产生额外开销为防止多线程同时访问时争抢造成的数据安全问题需要使用互斥锁但是需要消耗大量的资源两个多个线程都要等待对方完成某个操作才能进行下一步这时就会发生死锁。 多线程的实现有多种方式NSThread、NSObject、NSOperation和GCD其中较常用的是GCD首先是几种多线程之间优缺点比较前人总结直接粘过来的 NSThread (抽象层次低) 优点轻量级简单易用可以直接操作线程对象缺点: 需要自己管理线程的生命周期线程同步。线程同步对数据的加锁会有一定的系统开销。 NSOperation (抽象层次中) 优点不需要关心线程管理数据同步的事情可以把精力放在学要执行的操作上。基于GCD是对GCD 的封装比GCD更加面向对象缺点: NSOperation是个抽象类使用它必须使用它的子类可以实现它或者使用它定义好的两个子类NSInvocationOperation、NSBlockOperation. GCD 全称Grand Center Dispatch (抽象层次高) 优点是 Apple 开发的一个多核编程的解决方法简单易用效率高速度快基于C语言更底层更高效并且不是Cocoa框架的一部分自动管理线程生命周期创建线程、调度任务、销毁线程。 缺点: 使用GCD的场景如果很复杂就有非常大的可能遇到死锁问题。 下面分别介绍一下基础操作 首先NSThread开辟子线程 NSThread *thread [[NSThread alloc] initWithTarget:self selector:selector(sayHi) object:nil];//手动开启子线程 [thread start]; [NSThread exit];//使用NSThread和NSObject实现的开辟线程系统会自动释放关不关都行 NSThread自动开辟子线程[NSThread detachNewThreadSelector:selector(sayHi) toTarget:self withObject:nil]; #pragma mark - NSObject 开启子线程 [self performSelectorInBackground:selector(sayHi) withObject:test];//开辟子线程sayHi方法在子线程中实现 [self performSelectorOnMainThread:selector(mainThreadChangeColor) withObject:nil waitUntilDone:YES];//返回到主线程 #pragma mark - NSOperation——————NSOperation不能直接进行多线程的创建需要借助NSOperationQueue NSInvocationOperation *operation [[NSInvocationOperation alloc] initWithTarget:self selector:selector(test) object:nil];//使用NSOperarion的第一个子类去创建多线程:NSInvocationOperation NSBlockOperation *blockOperation [NSBlockOperation blockOperationWithBlock:^{ NSLog(我是子线程); }];//使用NSOperation 的第二个子类创建子线程(这里可以只使用其中一个子类)若单独使用不使用NSOperationQueue只开辟一个子线程需要添加开启方法:[blockOperation start]; NSOperationQueue *queue [[NSOperationQueue alloc] init]; [queue addOperation:operation]; [queue addOperation:blockOperation]; #pragma mark - GCD dispatch_queue_t queue dispatch_queue_create(DISPATCH_QUEUE_SERIAL, 0);//开辟子线程串行队列 dispatch_queue_t queue dispatch_queue_create(0, DISPATCH_QUEUE_CONCURRENT);//开辟子线程并行队列串行与并行任选一个 //添加任务若有多个任务时//创建串行队列DISPATCH_QUEUE_SERIAL串行任务顺序执行;DISPATCH_QUEUE_CONCURRENT并行任务没有次序 dispatch_async(queue, ^{ NSLog(currentThread1 %, mainThread1 %, ismain %d, [NSThread currentThread], [NSThread mainThread], [NSThread isMainThread]);//这里的部分将会在子线程下实现 dispatch_async(dispatch_get_main_queue(), ^{ //返回主线程。这里的部分将会在主线程下实现。一般数据的解析加载在子线程中实现UI的刷新在主线程中实现最后会举了简单的小例子说明一下 }); }); #解析数据并刷新UI //url NSURL *url [NSURL URLWithString:http://www.baidu.com]; //创建请求 NSURLRequest *request [NSURLRequest requestWithURL:url]; //创建session NSURLSession *session [NSURLSession sharedSession]; //创建task NSURLSessionDataTask *task [session dataTaskWithRequest:request completionHandler:^(NSData * _Nullable data, NSURLResponse * _Nullable response, NSError * _Nullable error) { if (error nil) { //处理数据这里是使用异步block自动创建的子线程在这里处理数据防止主线程出现卡顿 //回到主线程刷新UI dispatch_async(dispatch_get_main_queue(), ^{ }); } }];NSOperationQueue与 GCD的比较 NSOperationQueue使用addOperation方法将NSOperation类型的对象加入队列并且该NSOperation类型的对象是NSOperation的子类创建的对象NSInvocationOperation和NSBlockOperation使用NSOperationQueue时不能出现start方法 GCD使用dispatch_queue_create方法创建子线程根据该方法内的参数的不同从而创建串行队列DISPATCH_QUEUE_SERIAL和并行队列DISPATCH_QUEUE_CONCURRENT; 使用dispatch_async添加任务 CGD的应用比较广泛在这里重点介绍一下 常用的主线程串行队列异步执行任务在主线程运行不会产生死锁。 1 dispatch_queue_t mainQueue dispatch_get_main_queue();
2 dispatch_async(mainQueue,^{
3 NSLog(ismain %d, [NSThread isMainThread]);//isman 1
4 });//只是在返回主线程的时候用这里并不是创建子线程 1 dispatch_queue_t mainQueue dispatch_queue_create(0, DISPATCH_QUEUE_SERIAL); 2 dispatch_async(mainQueue,^{ 3 NSLog(ismain %d, [NSThread isMainThread]);//isman 0;注意与上边代码的区别 //创建了子线程4 }); Global queue全局并发队列) //程序默认的队列级别队列执行的优先级,DISPATCH_QUEUE_PRIORITY_DEFAULT 0dispatch_queue_t globalQueue1 dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);//HIGHdispatch_queue_t globalQueue2 dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0);//LOWdispatch_queue_t globalQueue3 dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_LOW, 0);//BACKGROUNDdispatch_queue_t globalQueue4 dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_BACKGROUND, 0); 1 dispatch_queue_t globalQueue dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);3 dispatch_sync(globalQueue, ^{//isman 1;sync同步执行未开辟子线程可以简单理解为同步执行未开辟子线程异步执行开辟子线程特例除外
4 sleep(2.0);//同步执行会出现卡顿将“sync”改为“async”isman 0开辟了子线程NSLog(ismain %d, [NSThread isMainThread]);//当有多个任务时异步执行无顺序同步执行先加入先执行 6 }); Custom queue (自定义串/并行队列) dispatch_queue_t serialQueue dispatch_queue_create(com.dullgrass.serialQueue, DISPATCH_QUEUE_SERIAL);//若想定义并行队列将“DISPATCH_QUEUE_SERIAL”改为DISPATCH_QUEUE_CONCURRENTdispatch_async(serialQueue, ^{NSLog(ismain %d, [NSThread isMainThread]);}); 注意注意不要嵌套使用同步执行的串行队列任务 1 dispatch_queue_t serialQueue dispatch_queue_create(com.dullgrass.serialQueue, DISPATCH_QUEUE_SERIAL);
2 dispatch_sync(serialQueue, ^{ //无论该行是同步执行还是异步执行红色代码部分都不会执行
3 NSLog(会执行的代码);
4 dispatch_sync(serialQueue, ^{
5 NSLog(代码不执行);
6 });
7 }); dispatch_after延时添加到队列 1 dispatch_time_t delayTime3 dispatch_time(DISPATCH_TIME_NOW, 3*NSEC_PER_SEC);2 dispatch_time_t delayTime2 dispatch_time(DISPATCH_TIME_NOW, 2*NSEC_PER_SEC);3 dispatch_queue_t mainQueue dispatch_get_main_queue();4 NSLog(current task);5 dispatch_after(delayTime3, mainQueue, ^{6 NSLog(3秒之后添加到队列);7 });8 dispatch_after(delayTime2, mainQueue, ^{9 NSLog(2秒之后添加到队列);
10 });
11 NSLog(next task); dispatch_apply在给定的队列上多次执行某一任务在主线程直接调用会阻塞主线程去执行block中的任务。 dispatch_apply函数的功能把一项任务提交到队列中多次执行队列可以是串行也可以是并行dispatch_apply不会立刻返回在执行完block中的任务后才会返回是同步执行的函数。dispatch_apply正确使用方法为了不阻塞主线程一般把dispatch_apply放在异步队列中调用然后执行完成后通知主线程 1 dispatch_queue_t globalQueue dispatch_get_global_queue(0, 0);2 NSLog(current task);3 dispatch_async(globalQueue, ^{4 dispatch_queue_t applyQueue dispatch_get_global_queue(0, 0);5 //第一个参数3--block执行的次数6 //第二个参数applyQueue--block任务提交到的队列7 //第三个参数block--需要重复执行的任务8 dispatch_apply(3, applyQueue, ^(size_t index) {9 NSLog(current index %,(index));
10 sleep(1);
11 });
12 NSLog(dispatch_apply 执行完成);
13 dispatch_queue_t mainQueue dispatch_get_main_queue();
14 dispatch_async(mainQueue, ^{
15 NSLog(回到主线程更新UI);
16 });
17 });
18 NSLog(next task); 最后是多线程单例的书写方式别忘了在.h中声明 1 static MyHandle *myHandle nil;
2 (MyHandle *)shareMyHandle {
3 //在GCD中只执行一次用于记录内容是否执行过
4 static dispatch_once_t onceToken;
5 dispatch_once(onceToken, ^{
6 myHandle [[MyHandle alloc] init];
7 });
8 return myHandle;
9 } 转载于:https://www.cnblogs.com/bdlfbj/p/5515782.html