iOS多线程,NSThread ,NSOperationQueue ,GCD

来源:互联网 发布:单片机如何检测电压 编辑:程序博客网 时间:2024/05/16 10:25

iOS 多线程

1、进程跟线程

进程:

一个程序至少有一个进程,一个进程至少有一个线程、

        有独立的内存空间、

        同一个进程中的线程,共享内存中的内存跟资源、

     进程相当与一个静态容器,里面装了很多活动的线程。

线程:

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

     主线程的生命周前,和应用程序是绑定的,程序退出时候,主线程也就停止了、

     多线程,一个应用程序有多个线程,提高cpu的使用律,防止主线程堵塞、

     任何有可能堵塞主线程的的任务都不要再主线程执行(比如网络请求)。

进程跟线程:我觉得这样更好理解,进程就好比我们的道路(道路相当于进程),如果只有一个车道(车道相当于线程),车流量一多,就可能会造成道路的堵塞,万一前面哪辆车碰撞了。整个道路就瘫痪堵塞了。这样子话,我们就可以开辟多个车道(线程)来缓解、加速,交通状况。当然。如果车道(线程)增多就会增加资源的耗用。这也就是多线程会损耗一定的资源。一个道路可以开辟多个车道,(一个进程,里面可以有多个线程);
ps:个人理解,欢迎纠正大笑


2、iOS 多线程多种实现:

2.1、NSThread 

//------------------多线程1种方式

    NSThread *thread = [[NSThreadalloc]initWithTarget:self selector:@selector(thread) object:nil];

    [thread start];

      // ------------------多线程2种方式

   [NSThread detachNewThreadSelector:@selector(thread) toTarget:self withObject:nil];

// ------------------多线程3种方式

   [self performSelectorInBackground:@selector(thread) withObject:nil];

//回到主线程

   [self performSelectorOnMainThread:@selector(thread) withObject:nil waitUntilDone:NO];

NSlog(@"1111");

      waitUntilDone 等待上面方法执行后再执行下面的内容,例如:如果waitUntilDone为yes,则等待方法执行完再打印111,如果为no,就执行方法,与打印111,同步执行!

2.2、NSOperationQueue  

NSOperation 是一个抽象类,用来封装一个独立任务的代码与数据。不能直接使用该类,通过子类化或系统提供的子类来完成任务,NSOperationQueue是其系统提供的子类。
NSOperationQueue 用来管理operation 集合,决定他们的执行顺序,当一个 operation 被添加到queue后,一旦有多余的线程来执行这个 operation 。那么这个 operation 就会马上被执行。

// -------------------多线程4种方式

//直接代码块方式实现

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

[operationQ addOperationWithBlock:^{

       for (int i=0; i<50; i++) {

           NSLog(@"线程1111%d",i);

        }  }];

// ------------------多线程5种方式

    //创建线程队列(线程池)

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

   //线程的最大并发数,(如果有五个任务,并发为2的话,就是先执行前面两个,前面两个执行完一个才会轮到后面的任务执行)

   operationQ.maxConcurrentOperationCount = 2;

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

   //线程的优先级

   [inOperation setQueuePriority:NSOperationQueuePriorityVeryLow];

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

    //线程的优先级  

  [inOperation2 setQueuePriority:NSOperationQueuePriorityHigh];

//如果并发数是1得话、先添加进来的先执行

    [operationQ addOperation:inOperation];

[operationQ addOperation:inOperation2];

2.3、GCD(Grand central dispatch) 一个纯 c 语言 写的库,

GCD 的优点

     在多核的硬件上,性能更佳!

     并且操作简单,程序猿只需要告诉GCD你要执行什么任务。不需要编写任何线程管理的代码;

如何用?

     用之前先了解:

    GCD 的两个核心的概念:

    1、任务:执行什么样的操作

     2、队列:用来存放任务的。

任务

    1、同步,第一个参数要求我们放入一个队列,第二个参数就是我们要做的任务

     dispatch_sync(<#dispatch_queue_tqueue#>, <#^(void)block#>)

    2、异步

   dispatch_async(<#dispatch_queue_tqueue#>, <#^(void)block#>)


    .同步和异步的区别

    同步:在当前线程中执行

     异步:在另一条线程中执行

 队列

    1、并发队列Concurrent Dispatch Queue,多个任务同时执行

    dispatch_queue_t queue =dispatch_get_global_queue(<#long identifier#>, <#unsigned longflags#>)

    2、串行队列Serial Dispatch Queue),前一个任务执行完了,在执行下一个任务

     dispatch_queue_create(<#const char *label#>,<#dispatch_queue_attr_t attr#>)


 NSLog(@"主线程:%@",[NSThreadmainThread]);

        /*

    //(1)将异步执行,放入并发队列中

    dispatch_queue_t queue =dispatch_get_global_queue(0, 0);

    dispatch_async(queue, ^{

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

    });

    dispatch_async(queue, ^{

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

    });

    dispatch_async(queue, ^{

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

    });

    //总结:开辟三个新线程

    */

       /*

    //(2)将异步执行,放入串行队列中

    dispatch_queue_t queue =dispatch_queue_create("test", NULL);

    dispatch_async(queue, ^{

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

    });

    dispatch_async(queue, ^{

        NSLog(@"22222 ===== > %@",[NSThreadcurrentThread]);

    });

    dispatch_async(queue, ^{

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

    });

    //总结:会开启线程,但是只开启一个线程

    */

   

      /*

    //(3)将同步执行,放入串行队列中

    dispatch_queue_t queue =dispatch_queue_create("test", NULL);

    dispatch_sync(queue, ^{

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

    });

    dispatch_sync(queue, ^{

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

    });

    dispatch_sync(queue, ^{

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

    });

    //总结:不会开辟新线程

    */

    //(3)将同步执行,放入并发队列中

    dispatch_queue_t queue =dispatch_get_global_queue(0,0);

    dispatch_sync(queue, ^{

        NSLog(@"11111 ===== >%@",[NSThreadcurrentThread]);

    });

    dispatch_sync(queue, ^{

        NSLog(@"22222 ===== >%@",[NSThreadcurrentThread]);

    });

    dispatch_sync(queue, ^{

        NSLog(@"33333 ===== >%@",[NSThreadcurrentThread]);

    });

  dispatch_async(dispatch_get_main_queue(), ^{

            //回到主线程

        });

};

    //总结:不会开辟新线程,并发都失效了。

6)小结

   说明:同步函数不具备开启线程的能力,无论是什么队列都不会开启线程;异步函数具备开启线程的能力,开启几条线程由队列决定(串行队列只会开启一条新的线程,并发队列会开启多条线程)。

          同步函数

          1)并发队列:不会开线程

          2)串行队列:不会开线程

          异步函数

          1)并发队列:能开启N条线程

          2)串行队列:开启1条线程



3、总结:

在开发中要注意:
当你启动新线程去执行某个任务的时候(比如,做网络请求),最终请求结束后,要回到主线程去更新ui。
回到主线程的方式”
1、

//回到主线程

    [self performSelectorOnMainThread:@selector(thread) withObject:nil waitUntilDone:NO];

NSlog(@"1111");

      waitUntilDone 等待上面方法执行后再执行下面的内容,例如:如果waitUntilDone为yes,则等待方法执行完再打印111,如果为no,就执行方法,与打印111,同步执行!


2、

        dispatch_async(dispatch_get_main_queue(), ^{

           //回到主线程

        });

感谢纠正!

ps:每天进步一点点,做一个快乐的程序猿!
0 0