<pre name="code" class="objc"> 通过下面一个例子来了解一下多线程的应用场景,我们可以通过点击按钮来开始或者暂停动画的播放,但是当我们点击另一个按钮时,
就会执行一个方法,在该方法中循环打印一个很大的数字,在打印过程中,再通过点击播放/暂停按钮来控制动画已经无法做到了
,这时屏幕已经卡死,必须等待打印完成,才能控制动画的播放。如何既能打印又能控制动画的播放那,可以利用多线程来完成,
将打印交给子线程去完成就可以了,下面讲了几种简单开启的子线程方法,非常详细。在进入例子之前先来了解一下线程的基础知识。
<pre name="code" class="objc">/**
* 进程:一个正在运行的程序,叫一个进程
多进程:多个程序正在运行,叫多进程
线程:一个程序或者说一个进程 都会有一个或多个线程 如果只有一个 我们叫他主线程 主线程负责用户能看见的任务 例如添加控件 刷新页面,除了主线程以外
都叫子线程, 线程之间是独立的没有任何联系,子线程一般负责用户不直接看到的任务 例如加载图片的过程 下载视频等。
线程要明确的:只要用户看得见的 或者 跟用户看得见有关的 都使用主线程 进行操作。 因为开启子线程操作的时候 是为了更好地用户体验
用户体验直接的表现为看到的或者点击的流畅性。
线程是耗费资源的,虽然可以多线程操作 可以提高用户体验 但是不建议 进行很多线程同时进行操作。
*/
#import "RootViewController.h"
@interface RootViewController ()
// 声明一个imageView
@property (nonatomic, retain) UIImageView *imageView;
@end
@implementation RootViewController
-(void)dealloc
{
[_imageView release];
[super dealloc];
}
- (void)viewDidLoad {
[super viewDidLoad];
[self addSubviews];
}
// 创建imageView并添加图片按钮
- (void)addSubviews
{
self.imageView = [[UIImageView alloc] initWithFrame:CGRectMake(50, 100, 200, 200)];
self.imageView.backgroundColor = [UIColor redColor];
[self.view addSubview:self.imageView];
[_imageView release];
// 播放一组图片
NSMutableArray *imageArray = [NSMutableArray array];
for (int i = 0; i < 3; i++) {
UIImage *image = [UIImage imageNamed:[NSString stringWithFormat:@"pic%d", i + 4]];
// 加进数组
[imageArray addObject:image];
}
// 设置播放属性
self.imageView.animationImages = imageArray;
self.imageView.animationDuration = 0.5;
self.imageView.animationRepeatCount = 0;
// 点击按钮 开始播再点击按钮停止播
UIButton *button = [UIButton buttonWithType:UIButtonTypeCustom];
button.frame = CGRectMake(100, 320, 50, 50);
button.backgroundColor = [UIColor blueColor];
[button setTitle:@"播放" forState:UIControlStateNormal];
[button setTitle:@"停止" forState:UIControlStateSelected];
[button addTarget:self action:@selector(actionButton:) forControlEvents:UIControlEventTouchUpInside];
[self.view addSubview:button];
// 点击另一个按钮 循环打印
UIButton *button1 = [UIButton buttonWithType:UIButtonTypeCustom];
button1.frame = CGRectMake(160, 320, 50, 50);
button1.backgroundColor = [UIColor blueColor];
[button1 setTitle:@"打印" forState:UIControlStateNormal];
[button1 addTarget:self action:@selector(actionPrint:) forControlEvents:UIControlEventTouchUpInside];
[self.view addSubview:button1];
//需要一边打印 一边还能 开关动画
// 解决方案:开启一个子线程去完成打印的工作
#pragma mark ----NSThread----
// 这是一个最轻量级的线程 可以开启线程和关闭线程
// 创建一个线程 就是给他一个方法去执行
// 创建一个子线程专门去打印
NSThread *thread = [[NSThread alloc] initWithTarget:self selector:@selector(actionPrint:) object:nil];
// 开启这个线程
[thread start];
// 注意:线程操作的时候
// 在主线程的时候 系统自动添加了一个 自动释放池 那么咱们在开启子线程的时候 也要添加一个自动释放池
// 如果你的线程开的比较多 会造成代码比较乱 阅读性不高
// 一般方法中 添加了自动释放池 基本上都是线程方法
#pragma mark ---NSObject
//NSObject也提供了开启线程的方法 也可以解决程序卡死问题
[self performSelectorInBackground:@selector(actionPrint:) withObject:nil];
//NSOperation也是抽象类 没有实现具体功能
//NSInvocationOperation 调用操作(相当于任务)
//NSBlockOperation block操作(相当于任务)
//NSOperationQueue 线程队列
//创建任务一
NSInvocationOperation *invocation = [[NSInvocationOperation alloc] initWithTarget:self selector:@selector(invocation1) object:nil];
// 创建任务二
NSBlockOperation *blockOP2 = [NSBlockOperation blockOperationWithBlock:^{
// block 块中 就相当于添加了任务
[self blockOP2];
}];
// 创建一个队列
NSOperationQueue *queue = [[NSOperationQueue alloc] init];
// 注意 添加任务前要设置依赖关系
// 依赖性(串行)
[invocation addDependency:blockOP2]; // 前面完成 后面才能开始
// 把任务添加到队列当中
[queue addOperation:invocation];
[queue addOperation:blockOP2];
// 设置线程最大并发数
queue.maxConcurrentOperationCount = 2;
// 需求 进行同步请求一张图片 不产生屏幕卡顿
// 思路:开启一个子线程 进行同步请求图片 图片加载完成后回到主线程 显示到imageView上
}
// 实现任务一
- (void)invocation1
{
// 子线程中添加一个自动释放池
@autoreleasepool {
//[NSThread currentThread] 当前线程的信息
//打印是否是主线程
// 打印出来的number 是线程的个数 第几个线程
NSLog(@"%@ 是不是主线程:%d", [NSThread currentThread], [NSThread isMainThread]);
}
}
// 创建任务二
- (void)blockOP2
{
@autoreleasepool {
NSLog(@"%@ 是不是主线程:%d", [NSThread currentThread], [NSThread isMainThread]);
}
}
// 点击按钮 开始播再点击按钮停止播
- (void)actionButton:(UIButton *)button
{
button.selected = !button.selected;
if (button.selected == YES) {
[self.imageView startAnimating];
} else {
[self.imageView stopAnimating];
}
}
// 循环打印 卡死程序
- (void)actionPrint:(UIButton *)button
{
// 添加一个自动释放池
@autoreleasepool {
for (int i = 0; i < 888888888; i++) {
NSLog(@"%d", i);
}
}
}
@end
iOS经典讲解之多线程应用场景
最新推荐文章于 2023-04-30 14:29:10 发布