ViewController.h
#import <UIKit/UIKit.h>
@interface ViewController : UIViewController
@end
ViewController.m
#import "ViewController.h"
@interface ViewController ()
@property(nonatomic,strong)NSLock *lock; // 系统提供好的锁类
@end
void function(void *str){
NSLog(@"这是个函数!GCD最下面自定义队列在用! %s",str);
}
int count = 10000;
@implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
self.lock = [[NSLock alloc]init];
}
// 五个按钮的五个方法
- (IBAction)normalAction:(UIButton *)sender {
NSLog(@"普通计算");
[self test];
}
// 封装计算的方法
-(void)test{
// 打印当前线程, 当前线程是否是主线程
NSLog(@"%@,%d",[NSThread currentThread],[[NSThread currentThread]isMainThread]);
// 自动释放池 (autoreleasepool)
// 在iOS里面,会自动为UI创建一个主线程,默认主线程分配的内存空间是1M,我们新开辟的子线程默认是512k,分配的大小必须是4的倍数,分配给子线程的空间,是用来存储变量的,所以512k是充分够用的
// iOS运行的时候,程序在主入口自动添加自动释放池,而我们自己创建的子线程是没有自动释放池的,所以需要我们手动添加
// 添加释放池的原因: 子线程共用堆内存,如果不及时回收,随着子线程数量的上升,以及大量使用便利构造器,会对系统本身造成很大的负担
@autoreleasepool {
// 计算1到635500000
NSUInteger sum = 0;
for (NSUInteger i = 0; i <= 635500000; i++) {
sum += i;
}
NSLog(@"%ld",sum);
}
// ****** 子线程回到主线程 ****** (线程间的通信) ******
// GCD
dispatch_async(dispatch_get_main_queue(), ^{
// 在这里面进行主线程任务的操作(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(@"在该方法内实现主线程UI的刷新");
}
#pragma mark - NSObject
- (IBAction)nsobjectAction:(UIButton *)sender {
NSLog(@"NSObject");
// 在后台执行 (开辟多线程最简单的方法)
[self performSelectorInBackground:@selector(test) withObject:nil];
}
#pragma mark - NSThread
- (IBAction)nsthreadAction:(UIButton *)sender {
NSLog(@"NSThread");
// NSThread 是一个轻量级的多线程, 创建方式有两种
// 第一种:
// 1.由init来创建, 并且需要手动开启
// NSThread *thread = [[NSThread alloc]initWithTarget:self selector:@selector(test) object:nil];
// // 2.开启线程
// [thread start];
// // 3.取消线程
// [thread cancel]; // 不需要的时候写它.一般很少用
// 第二种:
// 初始化的同时自动开启子线程
[NSThread detachNewThreadSelector:@selector(test) toTarget:self withObject:nil];
}
#pragma mark - NSOperation
- (IBAction)oprerationAction:(UIButton *)sender {
NSLog(@"NSOperationQueue");
// NSOperation 是一个抽象类,它有两个子类,一个是NSInvocationOperation,另一个是NSBlockOperation
// 在MVC里面属于M层, 封装了单个任务的数据和相关的代码, 一般我们使用子类
// NSOperation 只是一个操作,本身并无主线程子线程的区分,通常与NSOperationQueue结合使用
// 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 是线程操作队列,用来管理一组Operation对象,会根据实际需求创建出合适数量的子线程,完成任务的并发执行
NSOperationQueue *queue = [[NSOperationQueue alloc]init];
// 设置最大并发执行数(当最大并发执行数为一的时候,程序串行执行
[queue setMaxConcurrentOperationCount:1];
// 设置依赖关系 [A addDependency:B] ,若A依赖B,则B先执行,A再执行
// [invocationOperation addDependency:blockOperation];
// A→B→C
[blockOperation1 addDependency:invocation2];
[invocation2 addDependency:blockOperation2];
// 添加队列
// [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三种队列:
// 主队列
// 全局队列
// 自定义队列 (串行队列,并行队列)
__weak typeof(self)temp = self;
#pragma mark - 1.主队列
// 1.主队列 ※※※※※※
// 获取主队列生成一个串行的队列,队列里面的block块按照FIFO的顺序执行,实际上就是一个单线程队列
dispatch_queue_t queue = dispatch_get_main_queue();
// 往队列里面添加任务
// dispatch_async(queue, ^{
// [temp test];
// NSLog(@"1");
// });
// dispatch_async(queue, ^{
// [temp test];
// NSLog(@"2");
// });
// dispatch_async(queue, ^{
// [temp test];
// NSLog(@"3");
// });
// 延时任务 // ※※※ 延迟5秒后触发. 参数只需要写时间
// dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(5 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
//
// NSLog(@"赵哥今晚在如家402等你算数");
// });
// 这样很慢, 一般很少用!
// dispatch_sync(queue, ^{
// [temp test];
// });
//
#pragma mark - 全局队列 (并发执行,随机顺序执行)
// 2.全局队列
// dispatch_queue_t global = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
// 添加任务
// dispatch_async(global, ^{
// [temp test];
// NSLog(@"1");
// });
// dispatch_async(global, ^{
// [temp test];
// NSLog(@"2");
// });
// dispatch_async(global, ^{
// [temp test];
// NSLog(@"3");
// });
// 重复执行的任务 // 第一个参数:重复执行的次数. 第二个参数:指定执行的队列. // size_t是个类型, 后面要加上参数名
// dispatch_apply(5, global, ^(size_t t) {
// NSLog(@"执行到第%ld次",t);
// });
#pragma mark - 自定义队列
// 3.自定义队列
// 串行队列
// 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");
// });
//
//
// // 添加函数 // .._async_f
// dispatch_async_f(queue1, "testContext", function);
// 并行队列
dispatch_queue_t queue2 = dispatch_queue_create("com.baidu", DISPATCH_QUEUE_CONCURRENT);
// // 障碍执行
// // 该方法创建的任务在执行的时候,会先检查是否有其他任务正在执行, 若有,等待其执行完毕再执行,否则其他任务要等待它执行完毕之后再执行
// dispatch_barrier_async(queue2, ^{
// [temp test];
// NSLog(@"障碍");
// });
// // 分组任务
// dispatch_group_t group = dispatch_group_create();
// // 添加任务
// 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");
// });
//
// // 最后才会执行的方法
// dispatch_group_notify(group, queue2, ^{
// NSLog(@"最后,昭哥变成了数学家");
// });
// 购票: 定义并发队列 ,几个窗口同时抢
// 模拟购票系统
dispatch_queue_t queue3 = dispatch_queue_create("CCC", DISPATCH_QUEUE_CONCURRENT);
// 开始购票:需要添加任务
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 // 加锁是因为避免造成目标的抢夺 ************** @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创建五个按钮,分别是普通计算, NSObject, NSThread, NSOperationQueue, GCD.
在ViewController.m中分别是下面五个函数,需要自行建立关系.
- (IBAction)normalAction:(UIButton *)sender ;// 普通计算
- (IBAction)nsobjectAction:(UIButton *)sender ;// NSObject
- (IBAction)nsthreadAction:(UIButton *)sender ;// NSThread
- (IBAction)oprerationAction:(UIButton *)sender ;// NSOperationQueue
- (IBAction)gcdAction:(UIButton *)sender ;// GCD