IOS多线程开发-NSThread线程状态

线程状态分为isExecuting(正在执行)、isFinished(已经完成)、isCancellled(已经取消)三种。其中取消状态程序可以干预设置,只要调用线程的cancel方法即可。但是需要注意在主线程中仅仅能设置线程状态,并不能真正停止当前线程,如果要终止线程必须在线程中调用exist方法,这是一个静态方法,调用该方法可以退出当前线程。


//
//  ViewController.m
//  NSThread多线程并发
//
//  Created by aslan on 16/3/12.
//  Copyright © 2016年 aslan. All rights reserved.
//

#import "ViewController.h"
#import "KCImageData.h"

#define ROW_COUNT 5
#define COLUMN_COUNT 3
#define ROW_HEIGHT 100
#define ROW_WIDTH ROW_HEIGHT
#define CELL_SPACING 10

@interface ViewController ()


@property (nonatomic,strong)NSMutableArray * imageViews;

//存储线程
@property (nonatomic,strong)NSMutableArray * threads;

@end

@implementation ViewController

- (void)viewDidLoad {
    [super viewDidLoad];
    // Do any additional setup after loading the view, typically from a nib.
    [self layoutUI];
}

- (void)didReceiveMemoryWarning {
    [super didReceiveMemoryWarning];
    // Dispose of any resources that can be recreated.
}

#pragma mark 界面布局
- (void)layoutUI
{
    //创建多个图片控件用于显示图片
    _imageViews = [NSMutableArray array];
    
    for (int r = 0; r < ROW_COUNT; r++) {
        for (int c = 0; c < COLUMN_COUNT; c++) {
            UIImageView * imageView = [[UIImageView alloc]initWithFrame:CGRectMake(c*ROW_WIDTH+(c*CELL_SPACING), r*ROW_HEIGHT+(r*CELL_SPACING), ROW_WIDTH, ROW_HEIGHT)];
            
            imageView.contentMode = UIViewContentModeScaleAspectFit;
            
            
            [self.view addSubview:imageView];
            [_imageViews addObject:imageView];
        }
    }
    
    NSLog(@"imageView Cont = %ld",_imageViews.count);
    //添加开始按钮
    UIButton * button = [UIButton buttonWithType:UIButtonTypeRoundedRect];
    button.frame = CGRectMake(50, 500, 220, 25);
    [button setTitle:@"加载图片" forState:UIControlStateNormal];
    //添加方法
    [button addTarget:self action:@selector(loadImageWithMultiThread) forControlEvents:UIControlEventTouchUpInside];
    [self.view addSubview:button];

    //添加停止按钮
    UIButton * buttonStop = [UIButton buttonWithType:UIButtonTypeRoundedRect];
    buttonStop.frame=CGRectMake(160, 500, 100, 25);
    [buttonStop setTitle:@"停止加载" forState:UIControlStateNormal];
    [buttonStop addTarget:self action:@selector(stopLoadImage) forControlEvents:UIControlEventTouchUpInside];
    [self.view addSubview:buttonStop];
}


- (void)loadImageWithMultiThread
{
    //创建多个线程用于填充图片
    int count = ROW_COUNT * COLUMN_COUNT;
    
    //创建线程集合
    _threads = [NSMutableArray arrayWithCapacity:count];
    
    
    for (int i = 0; i < ROW_COUNT*COLUMN_COUNT; i++) {
        NSThread * thread = [[NSThread alloc]initWithTarget:self selector:@selector(loadImage:) object:[NSNumber numberWithInt:i]];
        thread.name = [NSString stringWithFormat:@"mythread_%i",i];
        
        //改变线程优先级
        if(	i == 14)//最后一个线程优先级改成最高
            thread.threadPriority = 1.0;
        else
            thread.threadPriority = 0.5;
        
     
        [_threads addObject:thread];
        
//        [thread start];
    }
    
    //循环启动线程
    for(int i = 0 ;i < count;i++)
    {
        NSThread * thread = _threads[i];
        [thread start];
    }
}

#pragma mark加载图片
-(void)loadImage:(NSNumber *)index
{
    //currentThread方法可以取得当前操作线程
    NSLog(@"current thread:%@",[NSThread currentThread]);
    
    int i = index.intValue;
    
    NSData * data = [self requestData:i];
    
    NSThread * currentThread = [NSThread currentThread];
    
    //如果当前线程处于取消状态,则退出当前线程
    if(currentThread.isCancelled)
    {
        NSLog(@"thread %@ will be cancelled!",currentThread);
        [NSThread exit];//取消当前线程
    }
    
    KCImageData * imageData = [[KCImageData alloc]init];
    imageData.index = i;
    imageData.data = data;
    
    [self performSelectorOnMainThread:@selector(updataImage:) withObject:imageData waitUntilDone:YES];
    
}

#pragma mark 将图片显示到界面
- (void)updataImage:(KCImageData *)imageData
{
    UIImage * image = [UIImage imageWithData:imageData.data];
    UIImageView * imageView = _imageViews[imageData.index];
    imageView.image = image;
}

- (NSData *)requestData:(int)index
{
    //对非最后一张图片加载线程 休眠2秒
    //在这里让其他线程休眠2秒,此时你就会看到最后一张图片总是第一个加载(除非网速特别差)
    if (index != 14) {
        [NSThread sleepForTimeInterval:2.0];
    }
    NSURL * url = [NSURL URLWithString:@"http://img.popoho.com/allimg/140703/2-140F3215917-lp.jpg"];
    NSData * data = [NSData dataWithContentsOfURL:url];
    return data;
}

#pragma mark 停止加载图片
- (void)stopLoadImage
{
    for (int i = 0; i < ROW_COUNT * COLUMN_COUNT; i++) {
        NSThread * thread = _threads[i];
        if(!thread.isFinished)
        {
            NSLog(@"stop thread i = %i",i);
            [thread cancel];
        }
    }
}

@end





使用NSThread在进行多线程开发过程中操作比较简单,但是要控制线程执行顺序并不容易(前面万不得已采用了休眠的方法),另外在这个过程中如果打印线程会发现循环几次就创建了几个线程,这在实际开发过程中是不得不考虑的问题,因为每个线程的创建也是相当占用系统开销的。

扩展--NSObject分类扩展方法

为了简化多线程开发过程,苹果官方对NSObject进行分类扩展(本质还是创建NSThread),对于简单的多线程操作可以直接使用这些扩展方法。

- (void)performSelectorInBackground:(SEL)aSelector withObject:(id)arg:在后台执行一个操作,本质就是重新创建一个线程执行当前方法。

- (void)performSelector:(SEL)aSelector onThread:(NSThread *)thr withObject:(id)arg waitUntilDone:(BOOL)wait:在指定的线程上执行一个方法,需要用户创建一个线程对象。

- (void)performSelectorOnMainThread:(SEL)aSelector withObject:(id)arg waitUntilDone:(BOOL)wait:在主线程上执行一个方法(前面已经使用过)。


Demo代码:

http://www.oschina.net/code/snippet_2290420_54644

你可能感兴趣的:(IOS多线程开发-NSThread线程状态)