04 多线程

来源:互联网 发布:高德软件股票行情 编辑:程序博客网 时间:2024/04/30 13:53

1.多线程的基本概念

每一个程序都有一个主线程,程序启动时创建(调用main来启动)

主线程的生命周期是和应用程序绑定的,程序结束时,主线程也就停止

多线程技术表示,一个应用程序有多个线程,使用多线程能提供cup的使用率,防止主线程阻塞

任何有可能堵塞主线程的任务不要在主线程执行(访问网络)

注意:

线程使用不是无节制的

只有主线程有直接修改UI的能力(子线程与主线程通信)

2.多线程技术


3.线程的创建与启动


 01.NSThread:

- (void)viewDidLoad {        [super viewDidLoad];    // 开启了一个子线程,主线程继续执行,子线程也继续执行    // 1、[NSThread detachNewThreadSelector:@selector(test1) toTarget:self withObject:nil];        // 2、alloc 创建线程需要手动开启    /*    NSThread *thread = [[NSThread alloc] initWithTarget:self selector:@selector(test1) object:nil];    // 手动开启线程    [thread start];        [self test2];    */        // 3、设置图片    imgView = [[UIImageView alloc] initWithFrame:CGRectMake(60, 100, 200, 200)];    imgView.backgroundColor = [UIColor redColor];    [self.view addSubview:imgView];        NSLog(@"current Thread : %@", [NSThread currentThread]);}- (void)refreshUI:(UIImage *)image{    imgView.image = image;}#pragma mark - 设置图片- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event{    //[NSThread detachNewThreadSelector:@selector(subThread:) toTarget:self withObject:@(2)];        // 开启后台线程(子线程)    [self performSelectorInBackground:@selector(subThread:) withObject:nil];}- (void)subThread:(NSNumber *)number{    // ARC    // 因为在子线程创建的自动释放的对象,是不能够入主线程的自动释放中的    @autoreleasepool {                NSLog(@"current Thread : %@", [NSThread currentThread]);                // 耗时操作        NSURL *url = [NSURL URLWithString:@"http://f.hiphotos.baidu.com/image/w%3D2048/sign=110ed40be9f81a4c2632ebc9e3126159/b3b7d0a20cf431add6d225464936acaf2edd9848.jpg"];        NSData *data = [NSData dataWithContentsOfURL:url];        UIImage *image = [UIImage imageWithData:data];                // 刷新UI 错误了!不能在子线程中刷新UI的事情,很有可能会崩溃        //imgView.image = image;                // 只能在主线程做刷新UI,涉及到主线程和子线程通信(NSObject中方法)        /**         *  从子线程回到主线程         *  (1)回到主线程的方法         *  (2)传递的参数可以为空         *  (3)YES,必须等待主线程refreshUI:         NO,不需要等待         */        [self performSelectorOnMainThread:@selector(refreshUI:) withObject:image waitUntilDone:YES];                // 假设子线程还有若干事情        // YES,必须走完refreshUI:        // NO,主线程继续执行,子线程也接着执行    }}#pragma mark - 开启了线程了,打印交替进行了(2条执行路径)- (void)test1{    for (int i = 0; i < 1000; i++) {                // 性能开销比较大        NSLog(@"task 1: %d", i);    }}- (void)test2{    for (int i = 0; i < 100; i++) {                // 性能开销比较大        NSLog(@"task 2: %d", i);    }}#pragma mark - NSLog 性能开销比较大- (IBAction)task1:(UIButton *)sender {        for (int i = 0; i < 10000; i++) {                // 性能开销比较大        //NSLog(@"task 1: %d", i);    }        //NSLog(@"task 1");}- (IBAction)task2:(UIButton *)sender {    for (int i = 0; i < 100000; i++) {            }        //NSLog(@"task 2");    }

NSThread的常用方法:

//获取当前线程对象+ (NSThread *)currentThread;//使当前线程睡眠指定的时间,单位为秒+ (void)sleepForTimeInterval:(NSTimeInterval)ti;//退出当前线程+ (void)exit;//判断当前线程是否为主线程+ (BOOL)isMainThread//启动该线程- (void)start


还学到了:

// 如果我们DEBUG模式【调试】(RELEASE模式【发布】)/** *  源代码 *  编译(目标代码).o                                     / Debug   系统库文件(冗余,多) *  链接(多个文件,用户定义文件,系统库文件) *                                   \ Release 系统库文件(少)  */#ifdef DEBUG    #define MYLog(...) NSLog(__VA_ARGS__)#else    #define MYLog(...)#endif



02.NSOperation

@interface ViewController (){    NSOperationQueue *queue;}@end@implementation ViewController/** *  阻塞主线程 - 耗时的操作 */- (void)viewDidLoad {        [super viewDidLoad];        // 同步:先做A【耗时操作、界面卡顿】,再去做B    // 异步:同时进行A、B和操作        // 1 同步操作    /*    NSInvocationOperation *op1 = [[NSInvocationOperation alloc] initWithTarget:self                                                                      selector:@selector(op1)                                                                        object:nil];    // 开启了操作,调用指定的方法    [op1 start];    */            // NSOperation 抽象类,不实例化    /**     * (1) NSInvocationOperation     * (2) NSBlockOperation     */    // 2 异步操作    NSInvocationOperation *op1 = [[NSInvocationOperation alloc] initWithTarget:self selector:@selector(op1) object:nil];    // 设置优先级    [op1 setQueuePriority:NSOperationQueuePriorityVeryLow];    NSInvocationOperation *op2 = [[NSInvocationOperation alloc] initWithTarget:self selector:@selector(op2) object:nil];    [op2 setQueuePriority:NSOperationQueuePriorityVeryHigh];    // 当子线程完成时    [op2 setCompletionBlock:^{        //        NSLog(@"YES : %@", [NSThread currentThread]);    }];        NSInvocationOperation *op3 = [[NSInvocationOperation alloc] initWithTarget:self selector:@selector(op3) object:nil];    [op3 setQueuePriority:NSOperationQueuePriorityLow];        NSInvocationOperation *op4 = [[NSInvocationOperation alloc] initWithTarget:self selector:@selector(op4) object:nil];    [op4 setQueuePriority:NSOperationQueuePriorityNormal];        NSBlockOperation *op5 = [NSBlockOperation blockOperationWithBlock:^{                //NSLog(@"op2 : %@", [NSThread currentThread]);                for (int i = 0; i < 10; i++) {            NSLog(@"block op5 is :%d", i);        }    }];    [op5 setQueuePriority:NSOperationQueuePriorityHigh];        // 一旦将操作对象放入“操作队列”中,这个操作就变了异步操作(开启一个线程)    // 此外,我们不需要将“操作”对象手动开启,当这个操作加入到“队列”中,事情开始了    queue = [[NSOperationQueue alloc] init];    // 设置队列的并发数    [queue setMaxConcurrentOperationCount:1];    //[queue addOperation:op1];    //[queue addOperation:op2];    //[queue addOperation:op3];    //[queue addOperation:op4];    //[queue addOperation:op5];         NSArray *ops = @[op1, op2, op3, op4, op5];    // YES 阻塞当前线程(主线程),必须等待所有“操作队列”结束之后    // NO  不会阻塞主线程    [queue addOperations:ops waitUntilFinished:NO];        // 3 设置依赖关系    /*    NSBlockOperation *op7 = [NSBlockOperation blockOperationWithBlock:^{        NSLog(@"hello op7");    }];        NSBlockOperation *op8 = [NSBlockOperation blockOperationWithBlock:^{        NSLog(@"hello op8");        // 根据栏目ID,请求具体内容    }];        NSBlockOperation *op9 = [NSBlockOperation blockOperationWithBlock:^{        NSLog(@"hello op9");        // 先请求栏目数据 NSArray【model】    }];        // 设置依赖关系,切记不要“循环依赖”  得出op9 op8 op7    [op7 addDependency:op8];    [op8 addDependency:op9];    queue = [[NSOperationQueue alloc] init];    [queue addOperations:@[op7, op8, op9] waitUntilFinished:NO];    */}- (void)op1{    //NSLog(@"op1 : %@", [NSThread currentThread]);        for (int i = 0; i < 10; i++) {                NSLog(@"op1 is : %d", i);            }    //子线程与主线程之间通信    //[self performSelectorOnMainThread:@selector(test) withObject:nil waitUntilDone:YES];        // 回到主线程    [[NSOperationQueue mainQueue] addOperationWithBlock:^{                NSLog(@"hello %@", [NSThread currentThread]);    }];}- (void)op2{    for (int i = 0; i < 10; i++) {                NSLog(@"op2 is : %d", i);            }}- (void)op3{    for (int i = 0; i < 10; i++) {                NSLog(@"op3 is : %d", i);            }}- (void)op4{    for (int i = 0; i < 10; i++) {                NSLog(@"op4 is : %d", i);            }}

同步是无法取消的。

还学了线程锁:

// synchronized 锁的作用    /*    @synchronized(self) {                if (_allTickts > 0) {                        // 线程睡眠(测试)            [NSThread sleepForTimeInterval:2];                        _allTickts--;                        NSLog(@"_allTickts : %d", _allTickts);        }else {                        NSLog(@"票已经卖了");        }    }*/        // NSLock    /*    [_lock lock];

03.GCD

- (void)viewDidLoad {        [super viewDidLoad];        //[self gcd1];        //[self gcd2];        [self gcd3];}- (void)gcd3{    dispatch_group_t group = dispatch_group_create();    dispatch_queue_t queue = dispatch_queue_create("com.wxhl.c", DISPATCH_QUEUE_CONCURRENT);        dispatch_group_async(group, queue, ^{                NSLog(@"t 1: %@", [NSThread currentThread]);                for (int i = 0; i < 20; i++) {            NSLog(@"t 1 : %d", i);        }            });        dispatch_group_async(group, queue, ^{                NSLog(@"t 2: %@", [NSThread currentThread]);                for (int i = 0; i < 20; i++) {            NSLog(@"t 2 : %d", i);        }            });        dispatch_group_notify(group, queue, ^{               NSLog(@"finish : %@", [NSThread currentThread]);            });            dispatch_group_t group1 = dispatch_group_create();    dispatch_queue_t queue1 = dispatch_queue_create("com.wxhl.c", DISPATCH_QUEUE_CONCURRENT);        dispatch_group_async(group1, queue1, ^{                NSLog(@"g 1: %@", [NSThread currentThread]);                for (int i = 0; i < 100; i++) {            NSLog(@"g 1 : %d", i);        }            });        dispatch_group_notify(group1, queue1, ^{               NSLog(@"finish");    });}- (void)gcd2{    // 死锁问题        // 串行队列    dispatch_queue_t queue = dispatch_get_main_queue();        // 主队列    dispatch_sync(queue, ^{        NSLog(@"sync1 : %@", [NSThread currentThread]);    });}- (void)gcd1{    /**     *  (1) 队列的名字 "com.wxhl.q"     *  (2) 队列的属性            a. DISPATCH_QUEUE_CONCURRENT (并发队列(global_queue),并发线程队列)            b. DISPATCH_QUEUE_SERIAL (串行队列 只会创建一个子线程,顺序执行(依赖))            c. dispatch_get_main_queue 主队列     *  (3) 是否开辟子线程,看对队列,和异步和同步无关,如果是主队列,在主线程中,其他队列都是创建了子线程     */        dispatch_queue_t queue = dispatch_queue_create("com.wxhl.q", DISPATCH_QUEUE_CONCURRENT);    /**     *  队列的优先级     */    //dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);        dispatch_async(queue, ^{                NSLog(@"t 1 : %@", [NSThread currentThread]);        for (int i = 0; i < 20; i++) {            NSLog(@"t 1 : %d", i);        }                /*         // 同步         dispatch_sync(dispatch_get_main_queue(), ^{                  NSLog(@"%@", [NSThread currentThread]);         });*/                // 异步(请参考 waitUntilDone:YES理解)        dispatch_async(dispatch_get_main_queue(), ^{                        //NSLog(@"%@", [NSThread currentThread]);                    });    });        dispatch_async(queue, ^{                NSLog(@"t 2 : %@", [NSThread currentThread]);        for (int i = 0; i < 20; i++) {            NSLog(@"t 2 : %d", i);        }            });        dispatch_async(queue, ^{                NSLog(@"t 3 : %@", [NSThread currentThread]);        for (int i = 0; i < 20; i++) {            NSLog(@"t 3 : %d", i);        }            });        //[NSThread detachNewThreadSelector:@selector(test1) toTarget:self withObject:nil];}- (void)test1{    // .....        [self performSelectorOnMainThread:@selector(refreshUI) withObject:nil waitUntilDone:YES];        // .....}- (void)refreshUI{    }




0 0