美文网首页
oc中多线程

oc中多线程

作者: 进阶的蚊子 | 来源:发表于2017-08-30 16:31 被阅读4次

关于多线程,在编程中那是必不可少的,现在我们就好好梳理一下多线程.

在 iOS 中其实目前主要有3套多线程方案,他们分别是:

NSThread

GCD

NSOperation & NSOperationQueue

NSThread

NSThread是经过苹果封装后的,并且完全面向对象的。所以你可以直接操控线程对象,非常直观和方便。

它的生命周期还是需要我们手动管理,所以并不推荐使用

//多线程处理

-(void)manyThreadHandle

{

//方法1

NSThread *thread = [[NSThread alloc] initWithTarget:self selector:@selector(makerun:) object:@"1"];

// 启动

[thread start];

//方法2  不用手动启动 自动启动

[NSThread detachNewThreadWithBlock:^{

NSLog(@"--方法2");

}];

//方法3  不用手动启动自动启动

[NSThread detachNewThreadSelector:@selector(makerun:) toTarget:self withObject:@"2"];

}

-(void)makerun:(NSThread*)thred

{

NSLog(@"多线程--%@",thred);

}

2017-08-30 16:01:24.863 runtimeTest[6579:165898] --方法2

2017-08-30 16:01:24.864 runtimeTest[6579:165897] 多线程--1

2017-08-30 16:01:24.864 runtimeTest[6579:165899] 多线程--2

在NSThread 中海油很多方法和属性

//取消线程

- (void)cancel;

//启动线程

- (void)start;

//判断某个线程的状态的属性

@property (readonly, getter=isExecuting) BOOL executing;

@property (readonly, getter=isFinished) BOOL finished;

@property (readonly, getter=isCancelled) BOOL cancelled;

//设置和获取线程名字

-(void)setName:(NSString *)n;

-(NSString *)name;

//获取当前线程信息

+ (NSThread *)currentThread;

//获取主线程信息

+ (NSThread *)mainThread;

//使当前线程暂停一段时间,或者暂停到某个时刻

+ (void)sleepForTimeInterval:(NSTimeInterval)time;

+ (void)sleepUntilDate:(NSDate *)date;

GCD 方法

GCD 这个名字是不是很霸气 ,天朝人都懂得.其实指的是Grand Central Dispatch(GCD)

GCD会自动合理地利用更多的CPU内核(比如双核、四核),最重要的是它会自动管理线程的生命周期(创建线程、调度任务、销毁线程),完全不需要我们管理,我们只需要告诉干什么就行。同时它使用的也是c语言,不过由于使用了 Block(Swift里叫做闭包),使得使用起来更加方便,而且灵活。这个方法比较实用简便,强烈推荐.

在GCD中,加入了两个非常重要的概念:任务队列

任务

任务:即操作,你想要干什么,说白了就是一段代码,在 GCD 中就是一个 Block,所以添加任务十分方便。任务有两种执行方式:同步执行异步执行,主要区别在于会不会阻塞当前线程,直到Block中的任务执行完毕!

同步执行:阻塞当前线程,不会开辟新的线程

异步执行:不会阻塞当前线,程会开辟新的线程

队列:用于存放任务。一共有两种队列,串行队列并行队列

放到串行队列的任务,GCD 会FIFO(先进先出)地取出来一个,执行一个,然后取下一个,这样一个一个的执行。简单说串行 就是单行车道 ,所有的车(任务)都只能按顺序走

放到并行队列的任务,GCD 也会FIFO的取出来,但不同的是,它取出来一个就会放到别的线程,然后再取出来一个又放到另一个的线程。这样由于取的动作很快,忽略不计,看起来,所有的任务都是一起执行的。简单说并行 就是多条车道 ,所有的车(任务)都可以在对应车道上走,和隔壁车道没什么影响

主队列  任何需要刷新 UI 的工作都要在主队列执行

dispatch_queue_t queue = dispatch_get_main_queue();

自己创建队列

//串行队列

dispatch_queue_t queue = dispatch_queue_create("tk22.bournes.testQueue", NULL);

dispatch_queue_t queue = dispatch_queue_create("tk22.bournes.testQueue", DISPATCH_QUEUE_SERIAL);

//并行队列

dispatch_queue_t queue = dispatch_queue_create("tk22.bournes.testQueue", DISPATCH_QUEUE_CONCURRENT);

//全局并行队列

dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);

队列组

队列组可以将很多队列添加到一个组里,这样做的好处是,当这个组里所有的任务都执行完了,队列组会通过一个方法通知我们。

//1.创建队列组

dispatch_group_t group = dispatch_group_create();

//2.创建队列

dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);

//多次使用队列组的方法执行任务, 只有异步方法

//执行3次循环

dispatch_group_async(group, queue, ^{

for (NSInteger i = 0; i < 3; i++) {

NSLog(@"group-01 - %@", [NSThread currentThread]);

}

});

//主队列执行8次循环

dispatch_group_async(group, dispatch_get_main_queue(), ^{

for (NSInteger i = 0; i < 8; i++) {

NSLog(@"group-02 - %@", [NSThread currentThread]);

}

});

//执行10次循环

dispatch_group_async(group, queue, ^{

for (NSInteger i = 0; i < 10; i++) {

NSLog(@"group-03 - %@", [NSThread currentThread]);

}

});

//4.都完成后会自动通知

dispatch_group_notify(group, dispatch_get_main_queue(), ^{

NSLog(@"完成 - %@", [NSThread currentThread]);

});

//运行结果

2017-08-30 16:21:36.201 runtimeTest[6843:174540] group-01 -{number = 3, name = (null)}          2017-08-30 16:21:36.201 runtimeTest[6843:174555] group-03 -{number = 4, name = (null)}         2017-08-30 16:21:36.202 runtimeTest[6843:174555] group-03 -{number = 4, name = (null)}        2017-08-30 16:21:36.202 runtimeTest[6843:174540] group-01 -{number = 3, name = (null)}         2017-08-30 16:21:36.202 runtimeTest[6843:174555] group-03 -{number = 4, name = (null)}        2017-08-30 16:21:36.202 runtimeTest[6843:174540] group-01 -{number = 3, name = (null)}         2017-08-30 16:21:36.202 runtimeTest[6843:174555] group-03 -{number = 4, name = (null)}        2017-08-30 16:21:36.202 runtimeTest[6843:174555] group-03 -{number = 4, name = (null)}        2017-08-30 16:21:36.202 runtimeTest[6843:174555] group-03 -{number = 4, name = (null)}        2017-08-30 16:21:36.203 runtimeTest[6843:174555] group-03 -{number = 4, name = (null)}        2017-08-30 16:21:36.203 runtimeTest[6843:174555] group-03 -{number = 4, name = (null)}        2017-08-30 16:21:36.203 runtimeTest[6843:174555] group-03 -{number = 4, name = (null)}        2017-08-30 16:21:36.203 runtimeTest[6843:174555] group-03 -{number = 4, name = (null)}        2017-08-30 16:21:36.206 runtimeTest[6843:174502] group-02 -{number = 1, name = main}         2017-08-30 16:21:36.207 runtimeTest[6843:174502] group-02 -{number = 1, name = main}          2017-08-30 16:21:36.207 runtimeTest[6843:174502] group-02 -{number = 1, name = main}          2017-08-30 16:21:36.207 runtimeTest[6843:174502] group-02 -{number = 1, name = main}          2017-08-30 16:21:36.207 runtimeTest[6843:174502] group-02 -{number = 1, name = main}          2017-08-30 16:21:36.208 runtimeTest[6843:174502] group-02 -{number = 1, name = main}         2017-08-30 16:21:36.208 runtimeTest[6843:174502] group-02 -{number = 1, name = main}         2017-08-30 16:21:36.208 runtimeTest[6843:174502] group-02 -{number = 1, name = main}          2017-08-30 16:21:36.209 runtimeTest[6843:174502] 完成 -{number = 1, name = main}

NSOperation和NSOperationQueue

NSOperation 是苹果公司对 GCD 的封装,完全面向对象,所以使用起来更好理解,有很多和GCD比较类似

NSOperation 和 NSOperationQueue分别对应 GCD 的任务 和 队列

NSOperation只是一个抽象类,所以不能封装任务它有 2 个子类用于封装任务。分别是:NSInvocationOperation和NSBlockOperation

当你新创建一个 Operation 后,需要手动的调用start方法来启动任务,它会默认在当前队列同步执行。当然你也可以在中途取消一个任务,只需要调用其cancel方法即可。

//1.创建NSInvocationOperation对象

NSInvocationOperation *operation = [[NSInvocationOperation alloc] initWithTarget:self selector:@selector(run) object:nil];

//2.开始执行

[operation start];

//1.创建NSBlockOperation对象

NSBlockOperation *operation = [NSBlockOperation blockOperationWithBlock:^{

NSLog(@"%@", [NSThread currentThread]);

}];

//添加多个Block

for (NSInteger i = 0; i < 5; i++) {

[operation addExecutionBlock:^{

NSLog(@"第%ld次:%@", i, [NSThread currentThread]);

}];

}

//2.开始任务

[operation start];

2017-08-30 16:33:12.868 runtimeTest[7014:179819]{number = 1, name = main}

2017-08-30 16:33:12.869 runtimeTest[7014:179819] 第3次:{number = 1, name = main}

2017-08-30 16:33:12.869 runtimeTest[7014:179819] 第4次:{number = 1, name = main}

2017-08-30 16:33:12.868 runtimeTest[7014:179888] 第1次:{number = 4, name = (null)}

2017-08-30 16:33:12.868 runtimeTest[7014:179892] 第0次:{number = 3, name = (null)}

2017-08-30 16:33:12.869 runtimeTest[7014:179889] 第2次:{number = 5, name = (null)}

根据结果可以知道打印的顺序是乱的 这个也符合我们异步的任务执行情况

//1.创建NSBlockOperation对象

NSBlockOperation *operation = [NSBlockOperation blockOperationWithBlock:^{

NSLog(@"%@", [NSThread currentThread]);

}];

//2.开始任务

[operation start];

创建队列

//主队列

NSOperationQueue *queue = [NSOperationQueue mainQueue];

//1.创建一个其他队列

NSOperationQueue *queue = [[NSOperationQueue alloc] init];

//2.创建NSBlockOperation对象

NSBlockOperation *operation = [NSBlockOperation blockOperationWithBlock:^{

NSLog(@"%@", [NSThread currentThread]);

}];

//3.添加多个Block

for (NSInteger i = 0; i < 2; i++) {

[operation addExecutionBlock:^{

NSLog(@"第%ld次:%@", i, [NSThread currentThread]);

}];

}

//4.队列添加任务

[queue addOperation:operation];

2017-08-30 16:35:56.163 runtimeTest[7073:181494]{number = 3, name = (null)}

2017-08-30 16:35:56.163 runtimeTest[7073:181537] 第0次:{number = 4, name = (null)}

2017-08-30 16:35:56.163 runtimeTest[7073:181538] 第1次:{number = 5, name = (null)}

NSOperation有一个非常实用的功能,那就是添加依赖 和gcd中的队列组管理有点类似.有点啰嗦了,就先介绍这些吧,以后有时间会更新.

相关文章

  • iOS多线程

    OC中的多线程 OC中多线程根据封装程度可以分为三个:NSThread、GCD和NSOperation,本文主要讲...

  • iOS多线程编程

    OC中的多线程 OC中多线程根据封装程度可以分为三个层次:NSThread、GCD和NSOperation,另外由...

  • iOS多线程编程

    OC中的多线程 OC中多线程根据封装程度可以分为三个层次:NSThread、GCD和NSOperation,另外由...

  • IOS知识总结——多线程

    OC中的多线程 OC中多线程根据封装程度可以分为三个层次:NSThread、GCD和NSOperation,另外由...

  • iOS多线程编程

    OC中的多线程 OC中多线程根据封装程度可以分为三个层次:NSThread、GCD和NSOperation,另外由...

  • iOS多线程编程

    OC中的多线程 OC中多线程根据封装程度可以分为三个层次:NSThread、GCD和NSOperation,另外由...

  • iOS中的多线程编程

    OC中的多线程 OC中多线程根据封装程度可以分为三个层次:NSThread、GCD和NSOperation,另外由...

  • 重温01-iOS多线程编程

    OC中的多线程 OC中多线程根据封装程度可以分为三个层次:NSThread、GCD和NSOperation,另外由...

  • swift中的"互斥锁"

    前言 脱产学习swift中, 从多线程开始, 遇到了类似于oc中的多线程资源抢夺问题..oc中的解决方案是利用 "...

  • oc中多线程

    关于多线程,在编程中那是必不可少的,现在我们就好好梳理一下多线程. 在 iOS 中其实目前主要有3套多线程方案,他...

网友评论

      本文标题:oc中多线程

      本文链接:https://www.haomeiwen.com/subject/qdatjxtx.html