美文网首页
iOS多线程

iOS多线程

作者: AlenChen | 来源:发表于2016-06-17 20:51 被阅读29次

    多线程的概念不再赘述,iOS开发中总的来讲可用的多线程方法一共有四种。

    多线程的优点

    能适当提高程序的执行效率

    能适当提高资源利用率(CPU、内存利用率)

    多线程的缺点

    创建线程是有开销的,iOS下主要成本包括:内核数据结构(大约1KB)、栈空间(子线程512KB、主线程1MB,也可以使用-setStackSize:设置,但必须是4K的倍数,而且最小是16K),创建线程大约需要90毫秒的创建时间

    如果开启大量的线程,会降低程序的性能

    线程越多,CPU在调度线程上的开销就越大

    程序设计更加复杂:比如线程之间的通信、多线程的数据共享

    pthread

    一套通用的多线程API

    适用于Unix\Linux\Windows等系统

    跨平台\可移植

    使用难度大

    NSThread

    面向对象,偶尔使用,需要手动管理生命周期,其实也只是需要你手动去开启线程。

    // 简单用法

    //创建线程

    NSThread*thread = [[NSThreadalloc]initWithTarget:selfselector:@selector(run:)object:@"jack"];

    thread.name=@"my-thread";

    //启动线程

    [threadstart];

    [NSThreaddetachNewThreadSelector:@selector(run:)toTarget:selfwithObject:@"rose"];

    // 消息传递

    [selfperformSelectorInBackground:@selector(run:)withObject:@"jack"];

    还有一些其他常用方法,具体不再赘述。

    GCD

    基于c语言,能够充分利用设备的多核,具体方法如下

    - (void)viewDidLoad {

    [superviewDidLoad];

    // Do any additional setup after loading the view, typically from a nib.

    //GCD:主要关注两个内容

    //同步执行,异步执行;

    //队列:主对列,全局子队列,自定义队列;

    //主队列:

    dispatch_queue_tmainQueue =dispatch_get_main_queue();//获取主队列;

    //获取全局子队列:

    //优先级:

    //    DISPATCH_QUEUE_PRIORITY_DEFAULT默认优先级:

    dispatch_queue_tglobalQueue =dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT,0);

    #if0

    //在主对列发起同步任务,主线程等待等待任务执行,任务又在主线程里面等待主线程,造成互相等待,卡顿:

    //在主队列发起同步任务:

    dispatch_sync(mainQueue, ^{

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

    });

    #endif

    #if0

    //在全局队列发起同步任务:

    dispatch_sync(globalQueue, ^{

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

    });

    #endif

    #if0

    //用于在子线程回到主线程执行:  (常用做法)  √

    dispatch_async(mainQueue, ^{

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

    });

    #endif

    #if0

    //异步任务,全局子队列:  (用到)  √

    //会开启子线程执行任务:

    //可以开启多条子线程:

    dispatch_async(globalQueue, ^{

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

    });

    dispatch_async(globalQueue, ^{

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

    });

    #endif

    #if0

    //参数二: 0表示串行队列:

    dispatch_queue_t customQueue1 = dispatch_queue_create("custom",0);

    //串行队列只创建一条子线程,所有任务在这条线程里串行执行:

    dispatch_async(customQueue1, ^{

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

    });

    dispatch_async(customQueue1, ^{

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

    });

    #endif

    //参数二: DISPATCH_QUEUE_CONCURRENT表示并发队列:

    dispatch_queue_tcustomQueue2 =dispatch_queue_create("custom2",DISPATCH_QUEUE_CONCURRENT);

    //并发队列,可以开启多条线程:

    dispatch_async(customQueue2, ^{

    NSLog(@"%@", [NSThreadcurrentThread]);

    });

    dispatch_async(customQueue2, ^{

    NSLog(@"%@", [NSThreadcurrentThread]);

    });

    //一段时间执行对应的代码:

    dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(2.0*NSEC_PER_SEC)),dispatch_get_main_queue(), ^{

    UIAlertView*a = [[UIAlertViewalloc]initWithTitle:@"弹框"message:nildelegate:nilcancelButtonTitle:nilotherButtonTitles:@"确定",nil];

    [ashow];

    });

    NSLog(@".....");

    //只会执行一次:

    //    static dispatch_once_t onceToken;

    //    dispatch_once(&onceToken, ^{

    //        <#code to be executed once#>

    //    });

    //    [SingleExample shareSingle];

    //    [[SingleExample alloc] init];

    //    [[SingleExample alloc] init];

    //    [UIApplication sharedApplication];

    //    [NSNotificationCenter defaultCenter];

    //    [NSFileManager defaultManager];

    NSLog(@"%p", [SingleExampleshareSingle]);

    NSLog(@"%p", [SingleExampleshareSingle]);

    NSLog(@"%p", [SingleExampleshareSingle]);

    //    NSLog(@"%p", [[SingleExample alloc] init]);

    //分组执行任务:

    //创建分组:

    dispatch_group_tgroup =dispatch_group_create();

    //异步执行第一组任务:

    dispatch_group_async(group, globalQueue, ^{

    NSLog(@"第一个任务%@", [NSThreadcurrentThread]);

    });

    dispatch_group_async(group, globalQueue, ^{

    NSLog(@"第二个任务%@", [NSThreadcurrentThread]);

    });

    //等待其他任务执行完才执行:

    dispatch_group_notify(group, globalQueue, ^{

    NSLog(@"第三个任务%@", [NSThreadcurrentThread]);

    });

    [NSThreaddetachNewThreadSelector:@selector(doSomeThing:)toTarget:selfwithObject:nil];

    }

    - (void)doSomeThing:(id)obj

    {

    //下载网络数据:

    //返回主线程刷新UI界面:

    dispatch_async(dispatch_get_main_queue(), ^{

    NSLog(@"refreshUI%@", [NSThreadcurrentThread]);

    });

    }

    单粒写法

    staticSingleExample*single =nil;

    @implementationSingleExample

    + (SingleExample*)shareSingle

    {

    staticdispatch_once_tonceToken;

    dispatch_once(&onceToken, ^{

    single= [[SingleExamplealloc]init];

    });

    returnsingle;

    }

    NSOperation

    基于GCD(底层是GCD)

    比GCD多了一些更简单实用的功能

    使用更加面向对象

    代码如下

    @interfaceViewController()

    //线程队列,也称为线程池;

    @property(nonatomic,strong)NSOperationQueue*queue;

    @end

    @implementationViewController

    - (NSOperationQueue*)queue

    {

    if(_queue==nil) {

    _queue= [[NSOperationQueuealloc]init];

    }

    return_queue;

    }

    - (void)viewDidLoad {

    [superviewDidLoad];

    // Do any additional setup after loading the view, typically from a nib.

    }

    - (void)doOp1:(id)obj

    {

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

    NSLog(@"op1");

    [NSThreadsleepForTimeInterval:1.0];

    }

    }

    - (IBAction)clickStart:(id)sender {

    //    NSOperation的子类

    //通过方法创建任务:

    //执行方法里面的代码:

    NSInvocationOperation*op1 = [[NSInvocationOperationalloc]initWithTarget:selfselector:@selector(doOp1:)object:nil];

    //通过block方法创建任务:

    //执行block里面的代码:

    NSBlockOperation*op2 = [NSBlockOperationblockOperationWithBlock:^{

    NSLog(@"op2");

    }];

    NSBlockOperation*op3 = [NSBlockOperationblockOperationWithBlock:^{

    NSLog(@"op3");

    }];

    //最大的线程个数:

    //    self.queue.maxConcurrentOperationCount = 1;  //串行执行;

    //依赖顺序关系:

    [op2addDependency:op1];// op2等待op1执行完才执行;

    [op3addDependency:op1];// op3等待op1执行完才执行;

    // op2,op3与op1串行;

    // op2和op3并发执行

    //把任务放到线程队列里:

    [self.queueaddOperation:op3];

    [self.queueaddOperation:op2];

    [self.queueaddOperation:op1];

    //    [op1 cancel];

    }

    - (IBAction)clickStop:(id)sender {

    //取消正在等待的任务:

    [self.queuecancelAllOperations];

    }

    @end

    下面说下线程安全

    在某些情况下,如果多个子线程同时访问同一个方法或者变量,就会导致信息错误,比如数据覆盖混乱等,那么在这种情况下就需要设置线程锁。

    线程锁就是锁住线程,他会等上一个子线程进入并执行完操作之后,下一个子线程才会进来执行操作,如果是成员变量的话,一般使用原子性,即natomic,如果是方法函数,则有两种方法

    一是NSLOCK

    创建NSLOCK

    NSLock*lock = [[NSLockalloc]init];

    //加锁

    [locklock];

    // 中间是访问的方法

    // method

    //解锁

    [lockunlock];

    第二种就是关键字synchronized

    示例方法

    while(1) {

    @synchronized(self) {

    // method

    }

    }

    相关文章

      网友评论

          本文标题:iOS多线程

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