/**
@param argc 参数长度
@param argv 参数值
*/
int main(int argc, char * argv[]) {
}
/*
runloop - 运行循环
1.保证程序不退出,也就是建立死循环
2.负责监听事件(网络事件,时钟事件,触摸事件)
3.如果没有事件发生,runloop进入休眠状态
4.渲染图片,在一次循环中渲染所有的图片
每一条线程上都会有一个runloop。但是默认不开启,想让线程不被释放,需要将该线程的runloop运行起来
屏幕每秒钟闪烁60次
模式:
默认模式-NSDefaultRunLoopMode
ui处理模式-UITrackingRunLoopMode(优先级高)(只能被ui事件触发)
占位模式 - NSRunLoopCommonModes 可以解决时钟事件和ui处理事件的冲突(有隐患)
模式上的事件:source timer observe
/*
source : 事件源
source0:非内核事件
source1:系统内核事件
observe : 观察者
timer : 时钟
*/
如果在时钟监听事件中执行耗时操作(线程睡眠,)会导致主线程被阻塞
线程归属cpu进行调度
*/
解决方案一:
使用占位模式解决事件冲突问题(如果在时钟监听事件中执行耗时操作(线程睡眠,)会导致主线程被阻塞)
- (void)viewDidLoad {
[super viewDidLoad];
NSTimer *timer = [NSTimer timerWithTimeInterval:1.f target:self selector:@selector(timerMethod) userInfo:nil repeats:YES];
[[NSRunLoop currentRunLoop] addTimer:timer forMode:NSRunLoopCommonModes];// 添加到占位模式中
}
- (void)timerMethod {
static int num = 0;
num ++;
NSLog(@"%@,%d",[NSThread currentThread],num);
}
解决方案二:
对方案隐患的问题解决和优化
在子线程中执行时钟会出现子线程开辟使用结束会自动释放,使用开启子线程runloop的模式解决该问题,在需要时在对子线程进行关闭或者停止runloop的运行循环
// 1.以关闭子线程runloop的方式解决
- (void)viewDidLoad {
[super viewDidLoad];
NSThread *thread = [[NSThread alloc] initWithBlock:^{
NSTimer *timer = [NSTimer timerWithTimeInterval:1.f target:self selector:@selector(timerMethod) userInfo:nil repeats:YES];
[[NSRunLoop currentRunLoop] addTimer:timer forMode:NSDefaultRunLoopMode];// 添加到占位模式中
// [[NSRunLoop currentRunLoop] run]; // 开启子线程runloop循环
while (!self.isFanished) {
// 每次RunLoop运行的时间
[[NSRunLoop currentRunLoop] runUntilDate:[NSDate dateWithTimeIntervalSinceNow:0.001]];
}
}];
[thread start];
}
- (void)timerMethod {
[NSThread sleepForTimeInterval:1.f]; // 模拟主线程阻塞
static int num = 0;
num ++;
NSLog(@"%@,%d",[NSThread currentThread],num);
}
// 2.以杀掉子线程的方式解决
- (void)viewDidLoad {
[super viewDidLoad];
NSThread *thread = [[NSThread alloc] initWithBlock:^{
NSTimer *timer = [NSTimer timerWithTimeInterval:1.f target:self selector:@selector(timerMethod) userInfo:nil repeats:YES];
[[NSRunLoop currentRunLoop] addTimer:timer forMode:NSDefaultRunLoopMode];// 添加到占位模式中
[[NSRunLoop currentRunLoop] run]; // 开启子线程runloop循环
}];
[thread start];
}
- (void)timerMethod {
if (self.isFanished) {
[NSThread exit]; // 杀掉当前线程
}
[NSThread sleepForTimeInterval:1.f]; // 模拟主线程阻塞
static int num = 0;
num ++;
NSLog(@"%@,%d",[NSThread currentThread],num);
}
- (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event {
self.isFanished = YES;
}
小知识:
[NSThread exit]; // 杀掉当前线程
可以通过该方法杀掉主线程,程序不会崩溃,但ui不会再进行处理
解决方案三:
使用gcd 不需要去额外处理runloop的问题
/**
全局队列
@param 0 优先级
@param 0 预留参数
*/
dispatch_queue_t queue = dispatch_get_global_queue(0, 0);
/**
创建定时器
@param DISPATCH_SOURCE_TYPE_TIMER 定时器类型
@param queue 全局队列可以进行异步处理
*/
dispatch_source_t timer = dispatch_source_create(DISPATCH_SOURCE_TYPE_TIMER, 0, 0, queue);
/**
DISPATCH_TIME_NOW 启动时间
1 * NSEC_PER_SEC = 1000,000,000 间隔时间 1秒
*/
dispatch_source_set_timer(timer, DISPATCH_TIME_NOW, 1 * NSEC_PER_SEC, 0 * NSEC_PER_SEC);
dispatch_source_set_event_handler(timer, ^{
NSLog(@"%@",[NSThread currentThread]);
});
// 启动定时器
dispatch_resume(timer);
在TableViewcell中添加多张高清大图,一次性加载多个时会出现卡顿现象,示例如下:https://github.com/feng562925462/iOSRunloop-
网友评论