iOS多线程GCD的简单使用

在iOS开发中,苹果提供了三种多线程技术,分别是:程序员

(1)NSThread多线程

(2)NSOperation异步

(3)GCDasync

简单介绍一下GCD的使用。spa

GCD全称 Grand Central Dispatch,能够称之为大中央调度。实际上GCD是管理着一个线程池,如何建立线程,如何回收线程,以及分配多少个线程,这些都是GCD来控制的。在开发中,程序员是不用操做线程的相关事情,程序员只须要把应该作的操做放到相应的队列里面便可。线程

一:自定义队列3d

GCD中有多种队列,其中自定义的队列有两种:串行队列和并行队列code

1:串行队列:队列中的任务只会顺序执行,且一次只可以执行一个任务。也就是说,执行完一个任务后,才会执行下一个任务blog

2:并行队列:能够一次执行多个任务。好比说并行队列中有10个任务,能够一次执行3个任务,这三个任务哪一个先执行完了,再接着执行剩下的任务。队列

注意:不管是串行队列仍是并行队列,他们都是FIFO(先进先出)的。也就是说,不管是哪一种队列,任务进队列的时间越早,其执行的时间就越早(只不过某些状况下任务执行的结束时间是不肯定的)。

GCD中有两种操做,分别是同步操做和异步操做

1:同步操做:不会新开线程

2:异步操做:会开启新的线程

两种操做和两种队列,组合为4种状况,实际上,在开发中,有些组合基本上是不会用到的。下面用程序描述一下四种组合。

组合一:串行队列+同步操做(不会新建线程,并且任务是一个一个的执行,所以实际上就是顺序执行),代码以下:

- (void)gcdDemo1
{
    //串行队列+同步操做
    dispatch_queue_t queue = dispatch_queue_create("gcddemo", DISPATCH_QUEUE_SERIAL);
    for(int i = 0; i < 10; ++i){
        dispatch_sync(queue, ^{
            NSLog(@"%@ %d",[NSThread currentThread],i);
        });
    }
}

执行结果:

number = 1,说明是主线程,没有新开线程。

组合二:串行队列+异步操做(由于任务要一个一个的执行,可是由于是异步操做,因此会开启一个新的线程,全部的任务都在新的线程上执行),代码以下:

- (void)gcdDemo1
{
    dispatch_queue_t queue = dispatch_queue_create("gcddemo", DISPATCH_QUEUE_SERIAL);
    //串行队列+异步操做
    for (int i = 0; i < 10; ++i){
        dispatch_async(queue, ^{
            NSLog(@"%@ %d",[NSThread currentThread],i);
        });
    }
}

执行结果:

number = 2,说明开启了一个新的子线程,但仍然是顺序执行。

组合三:并行队列+同步操做(由于同步操做不会开启新的线程,所以,即便并行队列能够一次开始多个任务,但实际上仍旧是每一个任务都在主线程上执行,且按顺序执行)。代码以下:

- (void)gcdDemo2
{
    dispatch_queue_t queue = dispatch_queue_create("gcddemo", DISPATCH_QUEUE_CONCURRENT);
    //并行队列+同步任务
    for(int i = 0; i < 10; ++i){
        dispatch_sync(queue, ^{
            NSLog(@"%@ %d",[NSThread currentThread],i);
        });
    }
}

执行结果:

没有开启新的线程,且按顺序执行。

组合四:并行队列+异步操做(并行队列会一次开始多个任务,且异步操做能够开启新的线程,所以同一时刻可能会同时执行多个任务,开启多个线程,且每一个任务的结束时间是不肯定的)。代码以下:

- (void)gcdDemo2
{
    dispatch_queue_t queue = dispatch_queue_create("gcddemo", DISPATCH_QUEUE_CONCURRENT);
    //并行队列+异步任务
    for(int i = 0; i < 10; ++i){
        dispatch_async(queue, ^{
            NSLog(@"%@ %d",[NSThread currentThread],i);
        });
    }
}

执行结果:

能够看到,开启了多个线程,且任务不是按顺序执行完的。

二:全局队列

为了方便开发,苹果还提供了有全局队列,全局队列其实是并行队列,所以,全局队列的执行结果和并行队列的执行结果是一致的。代码以下:

全局队列+同步任务:

- (void)gcdDemo3
{
    dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
    //全局队列+同步任务
    for (int i = 0; i < 10; ++i){
        //同步任务
        dispatch_sync(queue, ^{
            NSLog(@"%@ %d",[NSThread currentThread],i);
        });
    }
}

执行结果:

全局队列+异步任务:

- (void)gcdDemo3
{
    dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
    //全局队列+异步任务
    for(int i = 0; i < 10; ++i){
        dispatch_async(queue, ^{
            NSLog(@"%@ %d",[NSThread currentThread],i);
        });
    }
}

执行结果:

三:主队列

苹果还提供了一种队列是主队列,主队列是串行队列,可是和串行队列又有差别。主队列上的任务都应该在主线程上顺序执行,没有异步的概念。也就是说,即便是异步任务在主队列上执行,也不会开启新的线程。

主队列+异步任务:

- (void)gcdDemo4
{
    dispatch_queue_t queue = dispatch_get_main_queue();
    //主队列+异步任务
    for(int i = 0; i < 10; ++i){
        dispatch_async(queue,^{
            NSLog(@"%@ %d",[NSThread currentThread],i);
        });
    }
}

执行结果:

能够看到,没有开启新的线程,且是顺序执行。

主队列+同步任务(会阻塞线程),代码以下:

- (void)gcdDemo4
{
    dispatch_queue_t queue = dispatch_get_main_queue();
    //主队列+同步任务,会阻塞
    for(int i = 0; i < 10; ++i){
        dispatch_sync(queue, ^{
            NSLog(@"%@ %d",[NSThread currentThread],i);
        });
    }
}

阻塞缘由:

主队列中自己是有一个任务A的(主任务),且该任务A尚未执行完。在执行任务A的过程当中,又插入了新的同步任务B。咱们知道,串行队列中,必须先执行完一个任务后,才能继续执行另外一个任务。此时的状况时:

若想继续执行任务A,须要先把任务B执行完,若想继续执行任务B,须要先把任务A执行完,所以形成了阻塞。

在开发中,应该避免这种阻塞的状况。

相关文章
相关标签/搜索