<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