iOS之多线程---三种多线程技术

1.多线程的基本概念和用法
①进程:每一个进程都一是一个应用程序,都有独立的内存空间。(一个程序也可以由多个进程)同一个进程中的线程共享内存中的存储空间和资源
②线程:
每一个程序都有一个主线程,调用main来启动。
主线程的生命周期和应用程序绑定,程序退出时主线程停止。
任何可以阻塞主线程的任务不要再主线程中执行(比如访问网络)

2.多线程使用的注意
①线程使用不是无节制的:
iOS中的主线程的堆栈大小是1M(不可变)
从第二个线程开始都是512KB(不可变)
②只有主线程可以修改UI,渲染引擎工作在主线程中

3.IOS的三种多线程技术(本文主题)

①NSThread:每个NSThread对象对应一个线程
优:量级较轻
缺:需要自己管理线程的生命周期、线程同步、加锁、睡眠和唤醒等,
②NSOperation/NSOperationQueue:面向对象的线程技术
优:不需要关心线程管理、数据同步的事情,且是面向对象的
③GCD(Grand Central Dispatch):是基于C语言的框架,可以充分利用多核,是苹果推荐使用的多线程技术

下面对三种技术,用代码逐一讲解:

①NSThread

- (void)viewDidLoad {
    [super viewDidLoad];

    for (int i=0; i<10; i++) {
        //1.线程睡眠
        [NSThread sleepForTimeInterval:1];
        NSLog(@"主线程1: %d", i);
    }

    NSThread *thread = [[NSThread alloc] initWithTarget:self selector:@selector(thread1:) object:@"multiThread1"];
    //2.开始线程
    [thread start];

    for (int i=0; i<10; i++) {
        //3.获取当前线程
        NSThread *current = [NSThread currentThread];
        //4.判断当前线程是否是主线程
        BOOL isMain = [current isMainThread];
        if (isMain) {
            NSLog(@"主线程2: %d", i);
        }
    }
}

-(void) thread1:(NSString *) threadName{
    for (int i=0; i<10; i++) {
        NSLog(@"%@: %d", threadName, i);
        if (i == 5) {
            //5.退出线程
            [NSThread exit];
        }
    }
}

②NSOperationQueue

- (void)viewDidLoad {
    [super viewDidLoad];

    //1.创建线程队列
    NSOperationQueue *queue = [[NSOperationQueue alloc] init];

    //2.创建线程任务
    /*NSOperation介绍:
    是Cocoa中的一个抽象类,用来封装单个任务和代码执行一项操作,由于是抽象类,所以不能直接实例化使用,必须定义子类继承该抽象类来实现(常用的为NSInvocationOperation类,但是也可以自己继承重写NSOperation类)
     */
    NSInvocationOperation *op1 = [[NSInvocationOperation alloc] initWithTarget:self selector:@selector(thread1:) object:@"thread1"];
    NSInvocationOperation *op2 = [[NSInvocationOperation alloc] initWithTarget:self selector:@selector(thread2:) object:@"thread2"];

    //3.设置队列属性
        //1)设置并发数量
    queue.maxConcurrentOperationCount = 1;

        //2)暂停线程
    queue.suspended = YES;

        //3)设置线程优先级,需要先暂停线程才会生效
    op1.queuePriority = NSOperationQueuePriorityHigh;
    op2.queuePriority = NSOperationQueuePriorityVeryLow;

    //4.任务完成时调用block
    op1.completionBlock = ^{
        NSLog(@"op1已经完成");
    };

    //5.创建任务的另一种方法:block方式
    [queue addOperationWithBlock:^{
        //也是一个线程入口,和op1、op2一样是一个线程
        for (int k=0; k<10; k++) {
            NSLog(@"blockThread: %d", k);
        }
    }];

    [queue addOperation:op2];
    [queue addOperation:op1];

    //6.开始线程
    queue.suspended = NO;

    for (int k=0; k<10; k++) {
        NSLog(@"main: %i", k);
    }


}

-(void) thread1:(NSString *) threadName {
    for (int i=0; i<10; i++) {
        NSLog(@"%@: %d", threadName, i);
    }
}

-(void) thread2:(NSString *) threadName {
    for (int j=0; j<10; j++) {
        NSLog(@"%@: %d", threadName, j);
    }
}

③GCD

传送门:http://blog.csdn.net/u012526801/article/details/49004871

补充1:线程中的内存管理问题,NSRunloop和如何跳出线程

NSRunloop:
①线程的生命周期存在5个状态:新建、就绪、运行、阻塞、死亡
②NSRunLoop可以保持一个线程一直为活动状态,不会马上销毁掉
③应用举例:多线程中使用定时器时,必须使用Runloop。因为只有开启Runloop保持线程为活动状态,定时器才不会失效

跳出线程方法:
调用cancel方法,然后再线程方法中根据线程的isCancelled属性可以break出线程方法
①跳出单个线程:[thread1 cancel];
②队列中,跳出多个线程:[queue cancelAllOperations];

内存问题:
多线程创建的实例对象不会放入自动释放池,可能会导致内存泄露。需要手动放入自动重生池

举例:创建一个线程队列queue和一个线程类MyOperation,在queue中添加2个继承于MyOperation类的任务,实现以上补充内容中提到的知识点

以下是viewController中的代码:

- (void)viewDidLoad {
    [super viewDidLoad];

    _queue = [[NSOperationQueue alloc] init];
    _op1 = [[MyOperation alloc] initwithName:@"thread1"];
    _op2 = [[MyOperation alloc] initwithName:@"thread2"];

    [_queue addOperation:_op1];
    [_queue addOperation:_op2];

    _op1.completionBlock = ^ {
        NSLog(@"op1已经完成------------------");
    };

    _op2.completionBlock = ^ {
        NSLog(@"op2已经完成------------------");
    };

//    [self performSelector:@selector(afterDelay) withObject:nil afterDelay:0.1];
    [self performSelector:@selector(cancelAllThread) withObject:nil afterDelay:0.5];
}

-(void) afterDelay {
    [_op1 cancel];
}

-(void) cancelAllThread {
    [_queue cancelAllOperations];
}

以下是MyOperation类的具体实现:

#import <Foundation/Foundation.h>

@interface MyOperation : NSOperation
@property (nonatomic, copy) NSString *mask;

-(instancetype) initwithName:(NSString *)mask;
@end

//##############################################################

#import "MyOperation.h"

@implementation MyOperation

-(instancetype) initwithName:(NSString *)mask {
    if (self == [super init]) {
        _mask = mask;
    }
    return self;
}

-(void) main {
    //1.多线程创建的实例对象不会放入自动释放池,可能会导致内存泄露。需要手动放入自动重生池
    @autoreleasepool {

        [NSTimer scheduledTimerWithTimeInterval:1 target:self selector:@selector(timeAction) userInfo:nil repeats:YES];
        //2.开启Runloop来保持线程的存活状态
        [[NSRunLoop currentRunLoop] run];


        for (int i=0; i<1000; i++) {
            //3.cancel方法只是改变isCancelled属性,在线程实现方法中做判断,用于跳出线程方法。
            if (self.isCancelled) {
                break;
            }
            NSLog(@"%@: %d", self.mask, i);
        }
    }
}
-(void) timeAction {
}
@end
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值