GCD
1.什么是GCD?
-(void)testGlobalQueue { dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0); dispatch_async(queue, ^{ NSLog(@"1%@",[NSThread currentThread]); }); dispatch_async(queue, ^{ NSLog(@"2%@",[NSThread currentThread]); }); dispatch_async(queue, ^{ NSLog(@"3%@",[NSThread currentThread]); }); }
//2.用dispatch_async异步函数往串行队列添加任务
-(void)testAsyncQueue { //1.创建串行队列 dispatch_queue_t queue = dispatch_queue_create("mosuyanxue", NULL); //2.添加任务到串行队列中 dispatch_async(queue, ^{ NSLog(@"1%@",[NSThread currentThread]); }); dispatch_async(queue, ^{ NSLog(@"2%@",[NSThread currentThread]); }); dispatch_async(queue, ^{ NSLog(@"3%@",[NSThread currentThread]); }); }
//用同步函数往串行队列添加任务
-(void)testSyncQueue { dispatch_queue_t queue = dispatch_queue_create("mosuyanxue", NULL); dispatch_sync(queue, ^{ NSLog(@"1%@",[NSThread currentThread]); }); dispatch_sync(queue, ^{ NSLog(@"2%@",[NSThread currentThread]); }); dispatch_sync(queue, ^{ NSLog(@"3%@",[NSThread currentThread]); }); }
//4.用dispatch_sync同步函数往并发队列中添加任务
<span style="background-color: rgb(255, 255, 255);">-(void)testSyncQueue2 { dispatch_queue_t queue = dispatch_queue_create("mosuyanxue", NULL); dispatch_sync(queue, ^{ NSLog(@"1%@",[NSThread currentThread]); }); dispatch_sync(queue, ^{ NSLog(@"2%@",[NSThread currentThread]); }); dispatch_sync(queue, ^{ NSLog(@"3%@",[NSThread currentThread]); }); }</span>
//5.线程异步下载图片 主线程刷新UI
-(void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event { __block UIImage * image; UIImageView * imgView = [[UIImageView alloc]initWithFrame:CGRectMake(10, 100, 100, 100)]; [self.view addSubview:imgView]; dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0); dispatch_async(queue, ^{ NSURL * url = [NSURL URLWithString:@"http://pic80.nipic.com/file/20151013/12964311_203654101785_2.jpg"]; NSData * data = [NSData dataWithContentsOfURL:url]; image = [UIImage imageWithData:data]; NSLog(@"%@",data); dispatch_async(dispatch_get_main_queue(), ^{ imgView.image = image; }); }); }
延迟执行
[NSThread sleepForTimeInterval:3];//这个尽量不要使用,会卡死当前线程。 NSLog(@"%@",@"task"); dispatch_queue_t queue =dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0); dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(3 * NSEC_PER_SEC)), queue, ^{ NSLog(@"%@",@"task sleep 3s"); });
一次性代码
static dispatch_once_t onceToken; dispatch_once(&onceToken, ^{ <#code to be executed once#> });
可以用作单例的实现方法
队列组
-(void)testQueueGroup { //组 dispatch_group_t group = dispatch_group_create(); //队列 dispatch_queue_t queue = dispatch_queue_create(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0); dispatch_group_async(group, queue, ^{ NSLog(@"1%@",[NSThread currentThread]); }); dispatch_group_async(group, queue, ^{ NSLog(@"2%@",[NSThread currentThread]); }); dispatch_group_notify(group, queue, ^{ NSLog(@"%@",@"完成"); }); }2.NSThread
- (id)initWithTarget:(id)target selector:(SEL)selector object:(id)argument
+ (void)detachNewThreadSelector:(SEL)aSelector toTarget:(id)aTarget withObject:(id)anArgument
第一个是实例方法,第二个是类方法
selector :线程执行的方法,这个selector只能有一个参数,而且不能有返回值。
target :selector消息发送的对象
argument:传输给target的唯一参数,也可以是nil
第一种方式会直接创建线程并且开始运行线程,第二种方式是先创建线程对象,然后再运行线程操作,在运行线程操作前可以设置线程的优先级等线程信息
threadPriority
@property (readonly) BOOL isMainThread NS_AVAILABLE(10_5, 2_0);
+ (BOOL)isMainThread NS_AVAILABLE(10_5, 2_0); // reports whether current thread is main
+ (NSThread *)mainThread NS_AVAILABLE(10_5, 2_0);
@property (nullable, copy) NSString *name NS_AVAILABLE(10_5, 2_0);
@property double threadPriority NS_AVAILABLE(10_6, 4_0); // To be deprecated; use qualityOfService below
下载图片例子
线程下载完图片后怎么通知主线程更新界面呢?
[self performSelectorOnMainThread:@selector(updateUI:) withObject:image waitUntilDone:YES];
performSelectorOnMainThread是NSObject的方法,除了可以更新主线程的数据外,还可以更新其他线程的比如:用:performSelector:onThread:withObject:waitUntilDone:
线程同步
他们都可以通过
[ticketsCondition signal]; 发送信号的方式,在一个线程唤醒另外一个线程的等待。
比如:
我们可以使用指令 @synchronized 来简化 NSLock的使用,这样我们就不必显示编写创建NSLock,加锁并解锁相关代码。
- (void)doSomeThing:(id)anObj
{
@synchronized(anObj)
{
// Everything between the braces is protected by the @synchronized directive.
}
}
将需要执行的操作封装到NSOperation对象
NSOperation对象放入NSOperationQueue
系统自动queue中取operation
将取出的操作放入新线程执行。
NSOperation是抽象类 不具备封装操作能力,需要使用子类
使用NSOperation子类的方式有三种。
NSInvocationOperation
NSBlockOperation
自定义子类继承NSOperation实现内部相应的方法
-(void)testNSInvocationOperation { //1,创建操作对象 封装要执行的任务 NSInvocationOperation *operation = [[NSInvocationOperation alloc]initWithTarget:self selector:@selector(downLoad) object:nil]; //2.执行操作 [operation start]; //总结:默认情况下如果操作没有放队列中 那么默认是主线程 }
-(void)downLoad
{
NSLog(@"%@",@"逗我呢");
}
//BlockOperation
-(void)testBlockOperation
{
NSBlockOperation * operation = [NSBlockOperation blockOperationWithBlock:^{
NSLog(@"1%@",[NSThread currentThread]);
}];
[operation addExecutionBlock:^{
NSLog(@"2%@",[NSThread currentThread]);
}];
[operation addExecutionBlock:^{
NSLog(@"3%@",[NSThread currentThread]);
}];
[operation start];
//是否开启了新线程 取决于任务的个数。任务=1 主线程 任务>1开启新线程
}
/如果想异步执行任务 则需要queue队列的协助。
-(void)testOperationQueue
{
//1.封装操作
NSInvocationOperation * operation1 = [[NSInvocationOperation alloc]initWithTarget:self selector:@selector(download) object:nil];
NSInvocationOperation * operation2 = [[NSInvocationOperation alloc]initWithTarget:self selector:@selector(run) object:nil];
NSInvocationOperation * operation3 = [[NSInvocationOperation alloc]initWithTarget:self selector:@selector(run) object:nil];
//2.创建队列
NSOperationQueue * queue = [[NSOperationQueue alloc]init];
//3.将操作添加到队列中
[queue addOperation:operation1];
[queue addOperation:operation2];
[queue addOperation:operation3];
}
-(void)download
{
NSLog(@"%@",@"download");
}
-(void)run
{
NSLog(@"%@",@"runing");
}
operation最大并发数 MaxConcurrentOperationCount = 5以内 2-3为好。
//取消队列的所有操作
[queue cancelAllOperations];
//暂停
[queue setSuspended:YES];
//operation的优先级取值
//NSOpertaion之间可以设置操作依赖。
//如让a执行完之后 才能执行操作B。可以这么写:
[operation1 addDependency:operation2];
可以在不同的operationQueue之间设置依赖关系,但是不能相互依赖。
自定义Operation
创建类继承自NSOperation
然后在.h中定义需要的属性,代理和代理方法。在.m文件中main函数写自己需要的操作。
代码如下。
@implementation CustomOperation
//在main方法中实现操作
-(void)main
{
NSURL * url = [NSURL URLWithString:self.url];
NSData * data = [NSData dataWithContentsOfURL:url];
UIImage * image = [UIImage imageWithData:data];
if (self.delegate && [self.delegate respondsToSelector:@selector(downloadOperation:didFinishDownload:)]) {
[self.delegate downloadOperation:self didFinishDownload:image];
}
}
@end
#import <Foundation/Foundation.h>
@class CustomOperation;
#import <UIKit/UIKit.h>
@protocol CustomOperationDelegate<NSObject>
@optional
-(void)downloadOperation:(CustomOperation *)operation didFinishDownload:(UIImage *)image;
@end
@interface CustomOperation : NSOperation
@property (nonatomic,strong) NSIndexPath *indexpath;
@property (nonatomic,copy) NSString * url;
@property (nonatomic,assign) id<CustomOperationDelegate> delegate;
@end
检测网络状态
-(void)testNetStatus
{
//根据用户的网络状态进行处理
/*
wifi /3G自动下载高清图片
低速网络 下载缩略图
没有网络 显示离线缓存数据
苹果官方提供了一个Reachability 可检测网络状态。
*/
//wifi
Reachability * wifi = [Reachability reachabilityForLocalWiFi];
//手机自带网络功能
Reachability * conn= [Reachability reachabilityForInternetConnection];
if ([wifi currentReachabilityStatus ]!= NotReachable) {
NSLog(@"%@",@"wifi");
}else if ([conn currentReachabilityStatus] != NotReachable){
NSLog(@"%@",@"有手机网络");
}else{
NSLog(@"%@",@"没有网络");
}
}
Reachability还可以实时监控网络状态。添加通知,如果网络有问题就通知。