ViewController.h
#import <UIKit/UIKit.h>
@interface ViewController : UIViewController
@end
ViewController.m
#import "ViewController.h"
@interface ViewController ()
@property(nonatomic,strong)NSLock *lock; // 系統(tǒng)提供好的鎖類
@end
void function(void *str){
NSLog(@"這是個函數(shù)!GCD最下面自定義隊(duì)列在用! %s",str);
}
int count = 10000;
@implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
self.lock = [[NSLock alloc]init];
}
// 五個按鈕的五個方法
- (IBAction)normalAction:(UIButton *)sender {
NSLog(@"普通計(jì)算");
[self test];
}
// 封裝計(jì)算的方法
-(void)test{
// 打印當(dāng)前線程, 當(dāng)前線程是否是主線程
NSLog(@"%@,%d",[NSThread currentThread],[[NSThread currentThread]isMainThread]);
// 自動釋放池 (autoreleasepool)
// 在iOS里面,會自動為UI創(chuàng)建一個主線程,默認(rèn)主線程分配的內(nèi)存空間是1M,我們新開辟的子線程默認(rèn)是512k,分配的大小必須是4的倍數(shù),分配給子線程的空間,是用來存儲變量的,所以512k是充分夠用的
// iOS運(yùn)行的時候,程序在主入口自動添加自動釋放池,而我們自己創(chuàng)建的子線程是沒有自動釋放池的,所以需要我們手動添加
// 添加釋放池的原因: 子線程共用堆內(nèi)存,如果不及時回收,隨著子線程數(shù)量的上升,以及大量使用便利構(gòu)造器,會對系統(tǒng)本身造成很大的負(fù)擔(dān)
@autoreleasepool {
// 計(jì)算1到635500000
NSUInteger sum = 0;
for (NSUInteger i = 0; i <= 635500000; i++) {
sum += i;
}
NSLog(@"%ld",sum);
}
// ****** 子線程回到主線程 ****** (線程間的通信) ******
// GCD
dispatch_async(dispatch_get_main_queue(), ^{
// 在這里面進(jìn)行主線程任務(wù)的操作(UI刷新)
});
// NSObject自帶的方法
// (1)
[self performSelectorOnMainThread:@selector(backMainThread) withObject:nil waitUntilDone:YES];
// (2)
[self performSelector:@selector(backMainThread) onThread:[NSThread mainThread] withObject:nil waitUntilDone:YES];
}
-(void)backMainThread{
NSLog(@"在該方法內(nèi)實(shí)現(xiàn)主線程UI的刷新");
}
#pragma mark - NSObject
- (IBAction)nsobjectAction:(UIButton *)sender {
NSLog(@"NSObject");
// 在后臺執(zhí)行 (開辟多線程最簡單的方法)
[self performSelectorInBackground:@selector(test) withObject:nil];
}
#pragma mark - NSThread
- (IBAction)nsthreadAction:(UIButton *)sender {
NSLog(@"NSThread");
// NSThread 是一個輕量級的多線程, 創(chuàng)建方式有兩種
// 第一種:
// 1.由init來創(chuàng)建, 并且需要手動開啟
// NSThread *thread = [[NSThread alloc]initWithTarget:self selector:@selector(test) object:nil];
// // 2.開啟線程
// [thread start];
// // 3.取消線程
// [thread cancel]; // 不需要的時候?qū)懰?一般很少用
// 第二種:
// 初始化的同時自動開啟子線程
[NSThread detachNewThreadSelector:@selector(test) toTarget:self withObject:nil];
}
#pragma mark - NSOperation
- (IBAction)oprerationAction:(UIButton *)sender {
NSLog(@"NSOperationQueue");
// NSOperation 是一個抽象類,它有兩個子類,一個是NSInvocationOperation,另一個是NSBlockOperation
// 在MVC里面屬于M層, 封裝了單個任務(wù)的數(shù)據(jù)和相關(guān)的代碼, 一般我們使用子類
// NSOperation 只是一個操作,本身并無主線程子線程的區(qū)分,通常與NSOperationQueue結(jié)合使用
// NSInvocationOperation
// NSInvocationOperation *invocationOperation = [[NSInvocationOperation alloc]initWithTarget:self selector:@selector(test) object:nil];
//
// // NSBlockOperation
__weak typeof(self)temp = self;
// NSBlockOperation *blockOperation = [NSBlockOperation blockOperationWithBlock:^{
// [temp test];
// NSLog(@"這個是blockOperation操作之行的");
//
// }];
NSBlockOperation *blockOperation1 = [NSBlockOperation blockOperationWithBlock:^{
[temp test1];
}];
NSInvocationOperation *invocation2 = [[NSInvocationOperation alloc]initWithTarget:self selector:@selector(test2) object:nil];
NSBlockOperation *blockOperation2 = [NSBlockOperation blockOperationWithBlock:^{
[temp test3];
}];
// NSOperationQueue 是線程操作隊(duì)列,用來管理一組Operation對象,會根據(jù)實(shí)際需求創(chuàng)建出合適數(shù)量的子線程,完成任務(wù)的并發(fā)執(zhí)行
NSOperationQueue *queue = [[NSOperationQueue alloc]init];
// 設(shè)置最大并發(fā)執(zhí)行數(shù)(當(dāng)最大并發(fā)執(zhí)行數(shù)為一的時候,程序串行執(zhí)行
[queue setMaxConcurrentOperationCount:1];
// 設(shè)置依賴關(guān)系 [A addDependency:B] ,若A依賴B,則B先執(zhí)行,A再執(zhí)行
// [invocationOperation addDependency:blockOperation];
// A→B→C
[blockOperation1 addDependency:invocation2];
[invocation2 addDependency:blockOperation2];
// 添加隊(duì)列
// [queue addOperation:invocationOperation];
// [queue addOperation:blockOperation];
[queue addOperation:invocation2];
[queue addOperation:blockOperation1];
[queue addOperation:blockOperation2];
}
#pragma mark - GCD
- (IBAction)gcdAction:(UIButton *)sender {
NSLog(@"GCD");
// GCD三種隊(duì)列:
// 主隊(duì)列
// 全局隊(duì)列
// 自定義隊(duì)列 (串行隊(duì)列,并行隊(duì)列)
__weak typeof(self)temp = self;
#pragma mark - 1.主隊(duì)列
// 1.主隊(duì)列 ※※※※※※
// 獲取主隊(duì)列生成一個串行的隊(duì)列,隊(duì)列里面的block塊按照FIFO的順序執(zhí)行,實(shí)際上就是一個單線程隊(duì)列
dispatch_queue_t queue = dispatch_get_main_queue();
// 往隊(duì)列里面添加任務(wù)
// dispatch_async(queue, ^{
// [temp test];
// NSLog(@"1");
// });
// dispatch_async(queue, ^{
// [temp test];
// NSLog(@"2");
// });
// dispatch_async(queue, ^{
// [temp test];
// NSLog(@"3");
// });
// 延時任務(wù) // ※※※ 延遲5秒后觸發(fā). 參數(shù)只需要寫時間
// dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(5 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
//
// NSLog(@"趙哥今晚在如家402等你算數(shù)");
// });
// 這樣很慢, 一般很少用!
// dispatch_sync(queue, ^{
// [temp test];
// });
//
#pragma mark - 全局隊(duì)列 (并發(fā)執(zhí)行,隨機(jī)順序執(zhí)行)
// 2.全局隊(duì)列
// dispatch_queue_t global = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
// 添加任務(wù)
// dispatch_async(global, ^{
// [temp test];
// NSLog(@"1");
// });
// dispatch_async(global, ^{
// [temp test];
// NSLog(@"2");
// });
// dispatch_async(global, ^{
// [temp test];
// NSLog(@"3");
// });
// 重復(fù)執(zhí)行的任務(wù) // 第一個參數(shù):重復(fù)執(zhí)行的次數(shù). 第二個參數(shù):指定執(zhí)行的隊(duì)列. // size_t是個類型, 后面要加上參數(shù)名
// dispatch_apply(5, global, ^(size_t t) {
// NSLog(@"執(zhí)行到第%ld次",t);
// });
#pragma mark - 自定義隊(duì)列
// 3.自定義隊(duì)列
// 串行隊(duì)列
// dispatch_queue_t queue1 = dispatch_queue_create("AAA", DISPATCH_QUEUE_SERIAL);
// dispatch_async(queue1, ^{
// [temp test];
// NSLog(@"1");
// });
// dispatch_async(queue1, ^{
// [temp test];
// NSLog(@"2");
// });
// dispatch_async(queue1, ^{
// [temp test];
// NSLog(@"3");
// });
//
//
// // 添加函數(shù) // .._async_f
// dispatch_async_f(queue1, "testContext", function);
// 并行隊(duì)列
dispatch_queue_t queue2 = dispatch_queue_create("com.baidu", DISPATCH_QUEUE_CONCURRENT);
// // 障礙執(zhí)行
// // 該方法創(chuàng)建的任務(wù)在執(zhí)行的時候,會先檢查是否有其他任務(wù)正在執(zhí)行, 若有,等待其執(zhí)行完畢再執(zhí)行,否則其他任務(wù)要等待它執(zhí)行完畢之后再執(zhí)行
// dispatch_barrier_async(queue2, ^{
// [temp test];
// NSLog(@"障礙");
// });
// // 分組任務(wù)
// dispatch_group_t group = dispatch_group_create();
// // 添加任務(wù)
// dispatch_group_async(group, queue2, ^{
// [temp test];
// NSLog(@"1");
// });
// dispatch_group_async(group, queue2, ^{
// [temp test];
// NSLog(@"2");
// });
// dispatch_group_async(group, queue2, ^{
// [temp test];
// NSLog(@"3");
// });
//
// // 最后才會執(zhí)行的方法
// dispatch_group_notify(group, queue2, ^{
// NSLog(@"最后,昭哥變成了數(shù)學(xué)家");
// });
// 購票: 定義并發(fā)隊(duì)列 ,幾個窗口同時搶
// 模擬購票系統(tǒng)
dispatch_queue_t queue3 = dispatch_queue_create("CCC", DISPATCH_QUEUE_CONCURRENT);
// 開始購票:需要添加任務(wù)
dispatch_async(queue3, ^{
for (int i = 0; i < 100; i++) {
[temp buyTicket];
}
});
dispatch_async(queue3, ^{
for (int i = 0; i < 100; i++) {
[temp buyTicket];
}
});
}
-(void)test1{
NSLog(@"1");
}
-(void)test2{
NSLog(@"2");
}
-(void)test3{
NSLog(@"3");
}
// 購票方法
-(void)buyTicket{
// 自動釋放池 @autoreleasepool
@autoreleasepool {
// 加鎖 @synchronized // 加鎖是因?yàn)楸苊庠斐赡繕?biāo)的搶奪 ************** @synchronized
// @synchronized(self) {
// count--;
// NSLog(@"%d",count);
// }
// 用自己定義的鎖來加鎖
[_lock lock];
count--;
NSLog(@"%d",count);
[_lock unlock];
}
}
- (void)didReceiveMemoryWarning {
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
@end
之后在Main.storyboard創(chuàng)建五個按鈕,分別是普通計(jì)算, NSObject, NSThread, NSOperationQueue, GCD.
在ViewController.m中分別是下面五個函數(shù),需要自行建立關(guān)系.
- (IBAction)normalAction:(UIButton *)sender ;// 普通計(jì)算
- (IBAction)nsobjectAction:(UIButton *)sender ;// NSObject
- (IBAction)nsthreadAction:(UIButton *)sender ;// NSThread
- (IBAction)oprerationAction:(UIButton *)sender ;// NSOperationQueue
- (IBAction)gcdAction:(UIButton *)sender ;// GCD