iOS--多线程之GCD

      • GCD相关使用函数
    • 1_GCD 一一 基础介绍
    • 2_GCD 一一 延时操作
    • 3_GCD 一一 代码块只执行一次
    • 4_继续更新

GCD相关使用函数

1_GCD 一一 基础介绍

@implementation ViewController

#pragma mark - 基本概念
//1.两个核心的概念
//任务:想要做的事情(需要执行的操作)
//队列:存放任务的容器(特点是先进先出)

//2.四大名词
//(1)任务的执行方式(决定了能不能开启新的线程)
//同步:任务在当前线程中执行(不具备开启新线程的能力)--- 任务需要马上执行
//异步:任务在其他线程中执行(具备开启新线程的能力)--- 任务可以等当前函数结束后再执行
//(2)队列的类型
//并发:多个任务可以同时执行(前提是有多个线程)
//串行:队列中任务按顺序一个一个执行;必须是一个执行完,再执行下一个

//3.使用步骤
//(1)创建队列
//(2)将指定的任务放到创建好的队列中。(将任务放到队列中后,GCD会自动将队列中的任务取出来放到线程中执行)
#pragma mark - UITouch
- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event{
      [self test9];
    //[self test8];
    //[self test7];
    //[self test6];
    //[self test5];
    //[self test4];
    //[self test3];
    //[self test2];
    //[self test1];
}
#pragma mark - 队列组
//用来存放队列的
//作用:多个任务在不同的线程中异步执行,全部执行完毕后回到主线程
- (void)test9{
    //1.创建一个队列组(存放队列的)
    dispatch_group_t group = dispatch_group_create();
    //2.将任务添加到队列组的队列中
    //参数1:队列组
    //参数2:队列
    //参数3:任务
    dispatch_group_async(group, dispatch_get_global_queue(0, 0), ^{
        NSLog(@"1:%@", [NSThread currentThread]);
        [self downloadImage:@"http://yuting.local/shareX/1092.jpg"];
        NSLog(@"下载图片1");
    });
    dispatch_group_async(group, dispatch_get_global_queue(0, 0), ^{
        NSLog(@"2:%@", [NSThread currentThread]);
        [self downloadImage:@"http://img5.duitang.com/uploads/item/201602/25/20160225131806_AC8BP.jpeg"];
        NSLog(@"下载图片2"); 
    });
    //3.队列组中的所有任务执行完毕后才回到主线程
    //参数1:哪个组的任务全部完成
    //参数2:组的任务完成后执行哪个队列中的任务
    dispatch_group_notify(group, dispatch_get_main_queue(), ^{
        NSLog(@"回到了线程");
        NSLog(@"%@", [NSThread currentThread]); 
    });
}
#pragma mark - !!!线程间通信
- (void)test8{
    dispatch_async(dispatch_get_global_queue(0, 0), ^{
        NSLog(@"%@", [NSThread currentThread]);
        UIImage * image = [self downloadImage:@""];
        NSLog(@"%@", image);
        //将图片传回主线程(将任务放到主队列中)
        dispatch_async(dispatch_get_main_queue(), ^{
           //在主队列中需要执行的任务
            _imageView.image = image;
        });  
    });
}
- (UIImage *)downloadImage:(NSString *)path{
    //1.创建url
    NSURL * url = [NSURL URLWithString:path];
    NSData * data = [[NSData alloc] initWithContentsOfURL:url];
    UIImage * image = [UIImage imageWithData:data];
    //返回下载的图片
    return image;
}
#pragma mark - 主队列
//主队列:主队列是系统创建好,专门用来存储在主线程中执行的任务的队列。添加到主队列中的任务,只能在主线程中执行的。使用的时候只需要直接去拿。
//注意:只能在主队列中异步执行任务

//主队列:在主线程中按顺序执行
//同步:不开新的线程
//结果:死锁
- (void)test7{
    //1.拿到主队列
    dispatch_queue_t queue = dispatch_get_main_queue();
    NSLog(@"开始");
    //2.将任务添加到主队列中,同步执行
    for (int i = 0; i < 10; i++) { 
        dispatch_sync(queue, ^{
            [self longTimeOperation:i];
        });
    }
    NSLog(@"结束");
}
//主队列:在主线程中按顺序执行
//异步:在其他线程中执行(需要开启新的线程)
//结果:在主线程中按顺序一个一个执行
- (void)test6{
    //1.拿到主队列
    dispatch_queue_t queue = dispatch_get_main_queue();
    //2.将任务添加到主队列中,异步执行
    for (int i = 0; i < 10; i++) {
        dispatch_async(queue, ^{   
           [self longTimeOperation:i];
        }); 
    }
}
#pragma mark - 全局队列
//全局队列:系统为我们已经创建好的一个并发队列,使用的时候只需要直接去拿
- (void)test5{
    //1.拿到全局队列
    //参数1:队列优先级, 0
    //参数2:预留参数
    dispatch_queue_t queue = dispatch_get_global_queue(0, 0);
    //2.添加任务,异步执行
    for (int i = 0; i < 10; i++) {     
        dispatch_async(queue, ^{
            [self longTimeOperation:i];
        });
    }
}

#pragma mark - GCD的基本使用
//并发:可以多个任务同时执行
//异步:在其他线程中执行任务(可以开启新的线程)
//结果:多个任务在多个线程中同时执行(先“结束”,再执行任务)
- (void)test4{
    //1.创建并发队列
    dispatch_queue_t queue = dispatch_queue_create("bb", DISPATCH_QUEUE_CONCURRENT);
     NSLog(@"开始");
   //2.将任务添加到队列中,异步执行
    for (int i = 0; i < 10; i ++) {  
        dispatch_async(queue, ^{       
            [self longTimeOperation:i];
        });
    }
    NSLog(@"结束");
}
//并发:多个任务同时执行
//同步:在当前线程中执行(不会开启新的线程)
//结果:所有任务在主线程中按顺序一个一个执行(先执行任务,再结束)
- (void)test3{
    //1.创建并发队列
    //DISPATCH_QUEUE_CONCURRENT  并发
    dispatch_queue_t queue = dispatch_queue_create("aaa", DISPATCH_QUEUE_CONCURRENT);
    NSLog(@"开始");
    //2.将任务添加到队列中,同步执行
    for (int i = 0; i < 10; i++) {
        dispatch_sync(queue, ^{
            [self longTimeOperation:i];
        });
    }
    NSLog(@"结束");
}
//串行:任务一个一个按顺序执行
//异步:在其他线程中执行(开启新的线程)
//结果:在子线程中,任务按顺序一个一个执行(先“结束”,再执行任务)
- (void)test2{

    //1.创建串行队列
    dispatch_queue_t queue = dispatch_queue_create("aaa", NULL);

    NSLog(@"开始");
    //2.将任务添加到队列中,异步执行
    for (int  i = 0; i < 10; i++) {
        dispatch_async(queue, ^{
            [self longTimeOperation:i];
        });
    }

    NSLog(@"结束");

}


//串行:任务一个一个按顺序执行
//同步:在当前线程中执行(不开启新的线程)
//结果:在主线程中,任务按顺序一个一个执行(先执行任务然后再“结束”)

- (void)test1{

    //1.创建串行队列
    //dispatch_queue_t  队列类型
    //参数1:队列的标签(队列名),可以传任意的C语言字符串
    //参数2:队列属性,传入并发或者串行
    //DISPATCH_QUEUE_SERIAL (NULL)  串行
    //DISPATCH_QUEUE_CONCURRENT 并发
    dispatch_queue_t queue = dispatch_queue_create("abc", DISPATCH_QUEUE_SERIAL);

    //2.将一个任务添加到队列中(同步的)
    //参数1:队列
    //参数2:任务
//    dispatch_sync(queue, ^{
//       
//        [self longTimeOperation:0];
//       
//    });

    NSLog(@"开始");
    //将多个任务添加到队列中
    for (int i = 0; i < 10; i++) {

        dispatch_sync(queue, ^{

            [self longTimeOperation:i];
        });
    }
    NSLog(@"结束");
}
#pragma mark - 任务
- (void)longTimeOperation:(int)i{
        NSLog(@"%@:%d", [NSThread currentThread], i);
}
@end

2_GCD 一一 延时操作

使用GCD函数可以进行延时操作,该函数为:

dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(delayInSeconds * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
[xxManager showMessage:message];
});

现在我们来分解一下参数:
dispatch_time(DISPATCH_TIME_NOW,
(int64_t)(delayInSeconds * NSEC_PER_SEC)) :

其中:
DISPATCH_TIME_NOW:从现在开始计时
(int64_t)(delayInSeconds:自定义参数(比如 2)与后面参数结合表示延时的时间长度
NSEC_PER_SEC:在头文件中的定义如下:
(#define NSEC_PER_SEC 1000000000ull) /* nanoseconds per second */ 该参数表示从现在开始经过多少纳秒 dispatch_get_main_queue():表示主队列 ^{ }:表示一个block任务。
现在来测试一下经过多少纳秒之后,由主队列调度任务是异步执行还是同步执行,代码如下:

// when 时间 从现在开始经过多少纳秒
dispatch_time_t when = dispatch_time(DISPATCH_TIME_NOW, (int64_t)(1.0 * NSEC_PER_SEC));

void (^task)() = ^ {
    // 延迟操作执行的代码
    NSLog(@"%@", [NSThread currentThread]);
}; 
// 经过多少纳秒,由主队列调度任务异步执行
dispatch_after(when, dispatch_get_main_queue(), task);
// 先执行就是异步,后执行就是同步
NSLog(@"come here");

延时操作 执行的是异步操作

3_GCD 一一 代码块只执行一次

GCD中有个函数能够保证某段代码在程序运行过程中只被执行1次!该函数如下:

static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
//写入代码块
})

dispatch_once_t在头文件中得定义如下:

typedef long dispatch_once_t 由此可知该类型是个long类型。当onceToken等于0时就会执行block代码。

dispatch_once 是线程安全的,只要涉及到线程安全就会涉及到锁,dispatch_once内部也有一把锁,性能比互斥锁高!

利用该函数我们可以来写一个单例模式 单例模式可以保证在程序运行过程,一个类只有一个实例且该实例易于供外界访问,从而方便控制实例个数,并节约系统资源,当应用程序需要共享一份资源时就可以用单例模式来实现


+(instancetype)shareDataBaseManager{
static DataBaseManager *manager;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
if (!manager) {
manager = [[DataBaseManager alloc]initPrivate];
}
});
return manager;
}

4_//继续更新

你可能感兴趣的:(iOS--多线程)