1.Android四大組件之Server
特色:
- 提供后臺(tái)長(zhǎng)期運(yùn)行服務(wù)(如復(fù)雜計(jì)算菩鲜、下載园细、遠(yuǎn)程消息通知等等)
-
長(zhǎng)生命周期、沒(méi)有用戶(hù)界面接校、在后臺(tái)運(yùn)行
2. ISO的GCD與后臺(tái)處理進(jìn)程
GCD為Grand Central Dispatch的縮寫(xiě)猛频。
Grand Central Dispatch (GCD)是Apple開(kāi)發(fā)的一個(gè)多核編程的較新的解決方法。它主要用于優(yōu)化應(yīng)用程序以支持多核處理器以及其他對(duì)稱(chēng)多處理系統(tǒng)蛛勉。它是一個(gè)在線(xiàn)程池模式的基礎(chǔ)上執(zhí)行的并行任務(wù)鹿寻。在Mac OS X 10.6雪豹中首次推出,也可在IOS 4及以上版本使用诽凌。先來(lái)了解幾個(gè)概念
- 任務(wù)(Task):任務(wù)指的是當(dāng)前需要處理的一項(xiàng)工作
- 線(xiàn)程(Thread):線(xiàn)程是程序執(zhí)行流的最小單元毡熏。它是程序中一個(gè)單一的順序控制流程,在單個(gè)程序中可以同時(shí)運(yùn)行多個(gè)線(xiàn)程侣诵,分別完成不同的工作痢法,這就形成了多個(gè)線(xiàn)程。
- 進(jìn)程(Process):進(jìn)程可以認(rèn)為是當(dāng)前正在運(yùn)行的程序杜顺,它通常由多個(gè)線(xiàn)程組成财搁。
IOS開(kāi)發(fā)中,多線(xiàn)程開(kāi)發(fā)工具主要有:NSThread(屬于線(xiàn)程)躬络、NSOperation & NSOperationQueue尖奔、Pthreads、GCD
2.1 Dispatch object 和 Dispatch queue的概念
- Dispatch object
GCD對(duì)象被稱(chēng)為Dispatch object洗鸵。Dispatch object和其他的object-c對(duì)象一樣是采用引用計(jì)數(shù)機(jī)制的越锈,不過(guò)它有自己的引用、釋放函數(shù)膘滨。它使用dispatch_retain和dispatch_release函數(shù)來(lái)進(jìn)行內(nèi)存管理甘凭。(ARC模式下自動(dòng)釋放)
- Dispatch queue
Dispatch queue是一個(gè)對(duì)象,它可以接受任務(wù)火邓,并將任務(wù)以先到先執(zhí)行的順序來(lái)執(zhí)行丹弱。dispatch queue可以是并發(fā)的或串行的。并發(fā)任務(wù)會(huì)基于系統(tǒng)負(fù)載來(lái)合適地并發(fā)進(jìn)行铲咨,串行隊(duì)列同一時(shí)間只執(zhí)行單一任務(wù)躲胳。
GCD:有以下三種隊(duì)列類(lèi)型:
- Main queue:主隊(duì)列和主線(xiàn)程(Main Thread)功能相同。實(shí)際上纤勒,提交至主隊(duì)列的任務(wù)會(huì)在主線(xiàn)程中執(zhí)行坯苹。Main queue可以調(diào)用dispatch_get_main_queue來(lái)獲得,主要負(fù)責(zé)UI相關(guān)的工作摇天。
- Global queues:全局隊(duì)列是并發(fā)隊(duì)列粹湃,一次可以運(yùn)行多個(gè)任務(wù)恐仑,分為高、中(默認(rèn))和低三個(gè)優(yōu)先級(jí)隊(duì)列为鳄。調(diào)用dispatch_get_global_queue函數(shù)傳入優(yōu)先級(jí)來(lái)訪(fǎng)問(wèn)隊(duì)列裳仆。
- Private queue:用戶(hù)隊(duì)列,通過(guò)dispatch_queue_create函數(shù)創(chuàng)建孤钦。這些隊(duì)列是串行的歧斟,一次只能運(yùn)行一個(gè)任務(wù)。
//例子:點(diǎn)擊下載圖片
#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{
//創(chuàng)建自定義隊(duì)列
dispatch_queue_t downloadQueue = dispatch_queue_create(kDownloadQueue, NULL);
//為了保證線(xiàn)程安全偏形,用一個(gè)局部變量來(lái)保存要訪(fǎng)問(wèn)的變量值
dispatch_async(downloadQueue, ^{
//下載圖片静袖,下載成功返回NSData對(duì)象
NSData *imageData = [NSData dataWithContentsOfURL:[NSURL URLWithString:kImgUrl]];
if(imageData){
//關(guān)于UI的更新只能在主線(xiàn)程里進(jìn)行
dispatch_async(dispatch_get_main_queue(), ^{
//把NSData對(duì)象轉(zhuǎn)化為UIImage對(duì)象
UIImage *image = [UIImage imageWithData:imageData];
self.imageView.image = image;
//操作結(jié)束,在主隊(duì)列中執(zhí)行回調(diào)
dispatch_async(dispatch_get_main_queue(), completion);
});
}
});
//釋放自定義隊(duì)列
// dispatch_release(downloadQueue);
}
2.2 線(xiàn)程(NSThread)
- 創(chuàng)建線(xiàn)程的兩種方式:實(shí)例發(fā)和class方法
//實(shí)例
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;//假設(shè)100張票
soldAmounts = 0;
}
- (IBAction)workAction:(id)sender {
[self work];
}
-(void)work{
NSLog(@"work");
condition = [[NSCondition alloc]init];//初始化鎖對(duì)象
//初始化線(xiàn)程1
thread1 = [[NSThread alloc]initWithTarget:self selector:@selector(sellTicket) object:nil];
[thread1 setName:@"Thread1"];
[thread1 start];
//初始化線(xiàn)程2
thread2 = [[NSThread alloc]initWithTarget:self selector:@selector(sellTicket) object:nil];
[thread2 setName:@"T2222222222"];
[thread2 start];
}
-(void)sellTicket{
NSLog(@"sellTicket");
//通過(guò)循環(huán)壳猜,模擬買(mǎi)票場(chǎng)景
while (1) {
[condition lock];//上鎖
//還沒(méi)賣(mài)完勾徽,繼續(xù)買(mǎi)票
if(totalAmounts - soldAmounts > 0){
//線(xiàn)程暫停0.5秒,模擬用戶(hù)買(mǎi)票場(chǎng)景
[NSThread sleepForTimeInterval:0.1];
soldAmounts += 1; //模擬已經(jīng)買(mǎi)到一張票
NSLog(@"[線(xiàn)程:%@]剩余%d張票统扳,已經(jīng)售出%d張",[[NSThread currentThread]name],totalAmounts-soldAmounts,soldAmounts);
}else{
//所有票賣(mài)完喘帚,跳出循環(huán)
break;
}
[condition unlock];//解鎖
}
}
- 與主線(xiàn)程交互
[self performSelectorOnMainThread:@selector(fresh) withObject:nil waitUntilDone:NO];
//參數(shù)一:執(zhí)行刷新工作的函數(shù),
//參數(shù)二:fresh形參咒钟,可以傳遞nil
//參數(shù)三:No吹由,表示不阻塞
2.3后臺(tái)處理進(jìn)程
- 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(@"====任務(wù)完成了。朱嘴。倾鲫。。萍嬉。乌昔。。壤追。磕道。。行冰。溺蕉。。悼做。疯特。===>");
[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);
}
});
}