1.Android四大组件之Server
特色:
- 提供后台长期运行服务(如复杂计算、下载、远程消息通知等等)
-
长生命周期、没有用户界面、在后台运行
2. ISO的GCD与后台处理进程
GCD为Grand Central Dispatch的缩写。
Grand Central Dispatch (GCD)是Apple开发的一个多核编程的较新的解决方法。它主要用于优化应用程序以支持多核处理器以及其他对称多处理系统。它是一个在线程池模式的基础上执行的并行任务。在Mac OS X 10.6雪豹中首次推出,也可在IOS 4及以上版本使用。先来了解几个概念
- 任务(Task):任务指的是当前需要处理的一项工作
- 线程(Thread):线程是程序执行流的最小单元。它是程序中一个单一的顺序控制流程,在单个程序中可以同时运行多个线程,分别完成不同的工作,这就形成了多个线程。
- 进程(Process):进程可以认为是当前正在运行的程序,它通常由多个线程组成。
IOS开发中,多线程开发工具主要有:NSThread(属于线程)、NSOperation & NSOperationQueue、Pthreads、GCD
2.1 Dispatch object 和 Dispatch queue的概念
- Dispatch object
GCD对象被称为Dispatch object。Dispatch object和其他的object-c对象一样是采用引用计数机制的,不过它有自己的引用、释放函数。它使用dispatch_retain和dispatch_release函数来进行内存管理。(ARC模式下自动释放)
- Dispatch queue
Dispatch queue是一个对象,它可以接受任务,并将任务以先到先执行的顺序来执行。dispatch queue可以是并发的或串行的。并发任务会基于系统负载来合适地并发进行,串行队列同一时间只执行单一任务。
GCD:有以下三种队列类型:
- Main queue:主队列和主线程(Main Thread)功能相同。实际上,提交至主队列的任务会在主线程中执行。Main queue可以调用dispatch_get_main_queue来获得,主要负责UI相关的工作。
- Global queues:全局队列是并发队列,一次可以运行多个任务,分为高、中(默认)和低三个优先级队列。调用dispatch_get_global_queue函数传入优先级来访问队列。
- Private queue:用户队列,通过dispatch_queue_create函数创建。这些队列是串行的,一次只能运行一个任务。
//例子:点击下载图片
#define kDownloadQueue "KDownloadQueue"
#define kImgUrl @"https://ss0.bdstatic.com/5aV1bjqh_Q23odCf/static/superman/img/logo/bd_logo1_31bdc765.png"
- (IBAction)btnAction:(id)sender {
[self downloadImageFrom:kImgUrl Completion:^{
self.tipLabel.text = @"下载完毕";
}];
}
-(void)downloadImageFrom:(NSString *)url Completion:(void(^)(void))completion{
//创建自定义队列
dispatch_queue_t downloadQueue = dispatch_queue_create(kDownloadQueue, NULL);
//为了保证线程安全,用一个局部变量来保存要访问的变量值
dispatch_async(downloadQueue, ^{
//下载图片,下载成功返回NSData对象
NSData *imageData = [NSData dataWithContentsOfURL:[NSURL URLWithString:kImgUrl]];
if(imageData){
//关于UI的更新只能在主线程里进行
dispatch_async(dispatch_get_main_queue(), ^{
//把NSData对象转化为UIImage对象
UIImage *image = [UIImage imageWithData:imageData];
self.imageView.image = image;
//操作结束,在主队列中执行回调
dispatch_async(dispatch_get_main_queue(), completion);
});
}
});
//释放自定义队列
// dispatch_release(downloadQueue);
}
2.2 线程(NSThread)
- 创建线程的两种方式:实例发和class方法
//实例
NSThread *thread = [[NSThread alloc] initWithTarget:self selector:@selector(work) object:nil];
[thread start];
//class方法
[NSThread detachNewThreadSelector:@selector(work) toTarget:self withObject:nil];
- 同步与加锁
- (void)viewDidLoad {
// [super viewDidLoad];
// Do any additional setup after loading the view.
NSLog(@"cc2didLoad");
totalAmounts = 100;//假设100张票
soldAmounts = 0;
}
- (IBAction)workAction:(id)sender {
[self work];
}
-(void)work{
NSLog(@"work");
condition = [[NSCondition alloc]init];//初始化锁对象
//初始化线程1
thread1 = [[NSThread alloc]initWithTarget:self selector:@selector(sellTicket) object:nil];
[thread1 setName:@"Thread1"];
[thread1 start];
//初始化线程2
thread2 = [[NSThread alloc]initWithTarget:self selector:@selector(sellTicket) object:nil];
[thread2 setName:@"T2222222222"];
[thread2 start];
}
-(void)sellTicket{
NSLog(@"sellTicket");
//通过循环,模拟买票场景
while (1) {
[condition lock];//上锁
//还没卖完,继续买票
if(totalAmounts - soldAmounts > 0){
//线程暂停0.5秒,模拟用户买票场景
[NSThread sleepForTimeInterval:0.1];
soldAmounts += 1; //模拟已经买到一张票
NSLog(@"[线程:%@]剩余%d张票,已经售出%d张",[[NSThread currentThread]name],totalAmounts-soldAmounts,soldAmounts);
}else{
//所有票卖完,跳出循环
break;
}
[condition unlock];//解锁
}
}
- 与主线程交互
[self performSelectorOnMainThread:@selector(fresh) withObject:nil waitUntilDone:NO];
//参数一:执行刷新工作的函数,
//参数二:fresh形参,可以传递nil
//参数三:No,表示不阻塞
2.3后台处理进程
- Task completion
- (void)applicationDidEnterBackground:(UIApplication *)application {
[self backgroundHandler];
}
- (void)backgroundHandler {
NSLog(@"### -->backgroundinghandler");
UIApplication *app = [UIApplication sharedApplication];
bgTask = [app beginBackgroundTaskWithExpirationHandler:^{
dispatch_async(dispatch_get_main_queue(),^{
if( bgTask != UIBackgroundTaskInvalid){
bgTask = UIBackgroundTaskInvalid;
}
});
NSLog(@"====任务完成了。。。。。。。。。。。。。。。===>");
[app endBackgroundTask:bgTask];
}];
// Start the long-running task
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
while (true) {
NSLog(@"httptool .....");
sleep(1);
}
});
}