//
// ViewController.m
// GCD_demo
/*
1、什么是GCD?
GCD是Grand Central Dispatch的缩写。作用是:它主要用于优化应用程序以支持多核处理器以及其他对称多处理系统。它是一个在线程池模式的基础上执行的并行任务。
2、GCD的原理是??
GCD的工作原理是让一个程序,根据可用的处理资源,安排他们在任何可用的处理器核心上平行排队执行特定的任务。这个任务可以是一个功能或者一个程序段。
*/
// Created by MAC on 2016/11/16.
// Copyright © 2016年 NetworkCode小贱. All rights reserved.
//
#import "ViewController.h"
/* 一个类*/
#import "PersonModel.h"
@interface ViewController (){
UIImageView * imageView;
/* 创建一个定时器*/
dispatch_source_t timeSource;
}
@end
@implementation ViewController
typedef struct _Data {
int number;
} Data;
void test(){
NSLog(@"我是两一个测试函数");
};
void testNotify(){
};
void finalizer(void * context){
free(context);
};
- (void)viewDidLoad {
[super viewDidLoad];
// /* 用于主线程测试*/
// [self testMainQueue];
// /* 获取当前线程*/
// [self lookThread];
// /* 串行队列*/
// [self createSerialQueue];
// /* 并行队列*/
// [self createConcurrentQueue];
// /* 调用主线程*/
// [self createMainQueue];
// /*队列的停止和开启*/
// [self queueStop_or_Start];
// /* 线程组*/
// [self createGroupQueue];
// /* 执行一次的函数*/
// [self aloneDoMoths];
// /* 延时函数*/
// [self delayQueue];
// /* 定时器*/
// [self timingQueue];
// /* 设置对列的优先级*/
// [self setPriorityOfQueue];
// /* 等待所有队列执行完毕后在执行*/
// [self waitAllQueueStop];
// /* 线程的同步*/
// [self queueSynchronous];
// /* 并行同步线程之间插入处理其他事件*/
// [self queueInsertEvent];
// /* 延时处理*/
// [self afterQueue];
/* 给对列设置上下文*/
[self contextQueue];
// Do any additional setup after loading the view, typically from a nib.
}
#pragma mark 查看当前线程
-(void)lookThread{
NSLog(@"当前线程:%@",[NSThread currentThread]);
/*
输出:
当前线程:<NSThread: 0x608000079980>{number = 1, name = main}
*/
}
#pragma mark 创建一个串行的队列
-(void)createSerialQueue{
/* 创建一个串行队列*/
dispatch_queue_t serialQueue = dispatch_queue_create("com.zsj.www", NULL);
//dispatch_async_f(serialQueue, @"我是队列的描述", test);
/* 异步开启队列*/
dispatch_async(serialQueue, ^{
NSLog(@"异步开启串行的队列:%@",[NSThread currentThread]);
});
/* 同步开启的队列*/
dispatch_sync(serialQueue, ^{
NSLog(@"同步步开启串行的队列:%@",[NSThread currentThread]);
});
/*
输出:
2016-11-16 11:42:54.235 GCD_demo[1035:171404] 异步开启串行的队列:<NSThread: 0x608000261f00>{number = 3, name = (null)}
2016-11-16 11:42:54.235 GCD_demo[1035:171353] 同步步开启串行的队列:<NSThread: 0x60800007b240>{number = 1, name = main}
*/
}
#pragma mark 创建一个并发队列
-(void)createConcurrentQueue{
/* 这是创建并行队列*/
dispatch_queue_t concurrentQueue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
size_t number =10;
dispatch_apply(number, concurrentQueue, ^(size_t j) {
NSLog(@"%zu",j);
});
/* 输出:
2016-11-16 13:30:51.969 GCD_demo[1338:305600] 0
2016-11-16 13:30:51.969 GCD_demo[1338:305656] 2
2016-11-16 13:30:51.969 GCD_demo[1338:305659] 3
2016-11-16 13:30:51.969 GCD_demo[1338:305657] 1
2016-11-16 13:30:51.969 GCD_demo[1338:305600] 4
2016-11-16 13:30:51.969 GCD_demo[1338:305656] 5
2016-11-16 13:30:51.969 GCD_demo[1338:305659] 6
2016-11-16 13:30:51.969 GCD_demo[1338:305657] 7
2016-11-16 13:30:51.969 GCD_demo[1338:305600] 8
2016-11-16 13:30:51.969 GCD_demo[1338:305656] 9
*/
}
#pragma mark 调用主线程
-(void)createMainQueue{
/* 获取主线程*/
dispatch_queue_t mainQueue =dispatch_get_main_queue();
/* 获取一个并发队列*/
dispatch_queue_t concurrentQueue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
/* 异步下载图片*/
dispatch_async(concurrentQueue, ^{
/* 下载的地址*/
NSURL * url = [NSURL URLWithString:@"http://img3.duitang.com/uploads/item/201607/15/20160715120438_W4VHi.jpeg"];
NSData * data = [NSData dataWithContentsOfURL:url];
/* 调用主线程刷新视图*/
dispatch_async(mainQueue, ^{
imageView.image = [UIImage imageWithData:data];
});
});
}
#pragma mark 用于主线程测试
-(void)testMainQueue{
UIImageView * imageV = [[UIImageView alloc]initWithFrame:self.view.frame];
[self.view addSubview:imageV];
imageV.contentMode = UIViewContentModeScaleAspectFit;
imageView = imageV;
}
#pragma mark 队列的停止和恢复
-(void)queueStop_or_Start{
/* 创建一个队列*/
dispatch_queue_t serialQueue = dispatch_queue_create("com.s", NULL);
/* 给队列里面添加任务*/
dispatch_sync(serialQueue, ^{
NSLog(@"我是停止的串行");
});
/* 我们停止串行队列*/
dispatch_suspend(serialQueue);
/* 我们设置延时10秒后在开启串行队列*/
for (unsigned int i=0; i<10; ++i) {
NSLog(@"%d",i);
if (i==9) {
/* 开启我们停止的串行队列*/
dispatch_resume(serialQueue);
}
}
/*
注释:
这里的延时,必须在MianQueue中,其他异步的不执行
*/
/* 再次开启串行队列*/
dispatch_sync(serialQueue, ^{
NSLog(@"我是串行的开启");
});
/*
输出:
2016-11-16 15:38:49.120 GCD_demo[2184:587672] 我是停止的串行
2016-11-16 15:38:49.121 GCD_demo[2184:587672] 0
2016-11-16 15:38:49.121 GCD_demo[2184:587672] 1
2016-11-16 15:38:49.121 GCD_demo[2184:587672] 2
2016-11-16 15:38:49.122 GCD_demo[2184:587672] 3
2016-11-16 15:38:49.122 GCD_demo[2184:587672] 4
2016-11-16 15:38:49.168 GCD_demo[2184:587672] 5
2016-11-16 15:38:49.168 GCD_demo[2184:587672] 6
2016-11-16 15:38:49.168 GCD_demo[2184:587672] 7
2016-11-16 15:38:49.168 GCD_demo[2184:587672] 8
2016-11-16 15:38:49.169 GCD_demo[2184:587672] 9
2016-11-16 15:38:49.169 GCD_demo[2184:587672] 我是串行的开启
*/
/****
*
* 注释:
* dispatch_suspend和dispatch_resume对并行队列不起作用。
*/
/* 同步对列的停止和恢复测试*/
[self testConcurrentQueueStop_or_Start];
}
-(void)testConcurrentQueueStop_or_Start{
/* 创建一个同步队列*/
dispatch_queue_t concurrentQueue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
/* 在同步队列里面我们添加任务*/
dispatch_sync(concurrentQueue, ^{
NSLog(@"我是同步队列的停止");
});
/* 我们停止同步队列*/
dispatch_suspend(concurrentQueue);
/* 添加另一个任务*/
dispatch_sync(concurrentQueue, ^{
NSLog(@"我是同步队列的开启");
});
dispatch_resume(concurrentQueue);
/*
输出:
2016-11-16 15:52:56.089 GCD_demo[2213:615920] 我是同步队列的停止
2016-11-16 15:52:56.089 GCD_demo[2213:615920] 我是同步队列的开启
注释:
我们从输出看到,同步队列,我们无法使用dispatch_suspend停止。
*/
}
#pragma mark 队列组
-(void)createGroupQueue{
/* 创建一个队列组*/
dispatch_group_t groupQueue = dispatch_group_create();
/* 创建队列*/
dispatch_queue_t queue_1 = dispatch_queue_create("com.zsj", NULL);
dispatch_queue_t queue_2 = dispatch_queue_create("com.zsj", NULL);
/* 异步执行我们的任务*/
dispatch_group_async(groupQueue, queue_1, ^{
NSLog(@"我是异步线程组的第一个任务");
});
dispatch_group_async(groupQueue, queue_2, ^{
NSLog(@"我是异步线程组的第二个任务");
});
/* 我们监控线程组执行完毕*/
dispatch_group_notify(groupQueue, dispatch_get_main_queue(), ^{
NSLog(@"线程组的任务执行完毕");
});
/*
输出:
2016-11-16 16:32:10.852 GCD_demo[2415:733948] 我是异步线程组的第一个任务
2016-11-16 16:32:10.852 GCD_demo[2415:733946] 我是异步线程组的第二个任务
2016-11-16 16:32:11.026 GCD_demo[2415:733912] 线程组的任务执行完毕
*/
}
#pragma mark 单个队列的执行完毕的通知
-(void)singleQueueEndNotify{
/* 创建一个队列*/
dispatch_queue_t queue_single = dispatch_queue_create("com", NULL);
/* 我们异步执行队列*/
dispatch_async(queue_single, ^{
NSLog(@"单个队列执行完毕的测试");
});
// dispatch_notify(self,queue_single,testNotify);
}
#pragma mark 程序只执行一次
-(void)aloneDoMoths{
for (int i =0; i<3; ++i) {
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
NSLog(@"我是独自一次");
});
}
/*
输出:
2016-11-16 17:45:09.718 GCD_demo[2676:941076] 我是独自一次
*/
}
#pragma mark 延时
-(void)delayQueue{
NSLog(@"我是延时前的输出");
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(3 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
NSLog(@"我是延时3秒后的输出");
});
/*
输出:
2016-11-16 17:48:33.107 GCD_demo[2719:956176] 我是延时前的输出
2016-11-16 17:48:36.110 GCD_demo[2719:956176] 我是延时3秒后的输出
*/
}
#pragma mark 定时器
-(void)timingQueue{
/* 定义一个回调块内的可变的变量*/
__block int isMark = 0;
timeSource = dispatch_source_create(DISPATCH_SOURCE_TYPE_TIMER, 0, 0, dispatch_get_main_queue());
dispatch_source_set_timer(timeSource, DISPATCH_TIME_NOW, 1 * NSEC_PER_SEC, 0 * NSEC_PER_SEC);
/* 定时器每隔一秒都执行的代码块*/
dispatch_source_set_event_handler(timeSource, ^{
isMark++;
if (isMark==5) {
/* 取消定时器*/
dispatch_cancel(timeSource);
}
NSLog(@"是UI");
});
/* 启动定时器*/
dispatch_resume(timeSource);
/*
注释:
timeSource 对象必须是全局的对象,否则讲不执行
*/
}
#pragma mark 设置队列的优先级
-(void)setPriorityOfQueue{
/* 创建一个串行队列*/
dispatch_queue_t serialQueue = dispatch_queue_create("com.zsj", DISPATCH_QUEUE_SERIAL);
/* 将我们创建的串行队列放到全局中*/
dispatch_set_target_queue(serialQueue, dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_LOW, 0));
/* 我们异步执行队列*/
dispatch_async(serialQueue, ^{
NSLog(@"串行队列执行1");
});
dispatch_async(serialQueue, ^{
NSLog(@"串行队列执行2");
});
/* 我们一步执行高等级的队列*/
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0), ^{
NSLog(@"DISPATCH_QUEUE_PRIORITY_HIGH");
});
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
NSLog(@"DISPATCH_QUEUE_PRIORITY_DEFAULT");
});
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_BACKGROUND, 0), ^{
NSLog(@"DISPATCH_QUEUE_PRIORITY_BACKGROUND");
});
/* 输出:
2016-11-21 14:41:22.591 GCD_demo[2071:307532] DISPATCH_QUEUE_PRIORITY_HIGH
2016-11-21 14:41:22.591 GCD_demo[2071:307529] DISPATCH_QUEUE_PRIORITY_DEFAULT
2016-11-21 14:41:22.591 GCD_demo[2071:307530] 串行队列执行1
2016-11-21 14:41:22.591 GCD_demo[2071:307530] 串行队列执行2
2016-11-21 14:41:22.591 GCD_demo[2071:307532] DISPATCH_QUEUE_PRIORITY_BACKGROUND
*/
/* 并行队列的优先级测试*/
[self testConcurrentPriorityOfQueue];
}
-(void)testConcurrentPriorityOfQueue{
/*创建一个并行队列*/
dispatch_queue_t concurrentQueue = dispatch_queue_create("com.zsj", DISPATCH_QUEUE_CONCURRENT);
/* 设置队列的优先级*/
dispatch_set_target_queue(concurrentQueue, dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0));
/* 并行队列优先级测试*/
dispatch_async(concurrentQueue, ^{
NSLog(@"并行队列执行1");
});
dispatch_async(concurrentQueue, ^{
NSLog(@"并行队列执行2");
});
/* 我们一步执行高等级的队列*/
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0), ^{
NSLog(@"DISPATCH_QUEUE_PRIORITY_HIGH");
});
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
NSLog(@"DISPATCH_QUEUE_PRIORITY_DEFAULT");
});
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_BACKGROUND, 0), ^{
NSLog(@"DISPATCH_QUEUE_PRIORITY_BACKGROUND");
});
/* 输出:
2016-11-21 14:50:25.893 GCD_demo[2120:342088] DISPATCH_QUEUE_PRIORITY_DEFAULT
2016-11-21 14:50:25.893 GCD_demo[2120:342074] 并行队列执行1
2016-11-21 14:50:25.893 GCD_demo[2120:342077] 并行队列执行2
2016-11-21 14:50:25.893 GCD_demo[2120:342088] DISPATCH_QUEUE_PRIORITY_HIGH
2016-11-21 14:50:25.894 GCD_demo[2120:342074] DISPATCH_QUEUE_PRIORITY_BACKGROUND
或者
2016-11-21 15:01:39.373 GCD_demo[2173:386610] 并行队列执行1
2016-11-21 15:01:39.373 GCD_demo[2173:386607] DISPATCH_QUEUE_PRIORITY_DEFAULT
2016-11-21 15:01:39.373 GCD_demo[2173:386610] 并行队列执行2
2016-11-21 15:01:39.373 GCD_demo[2173:386607] DISPATCH_QUEUE_PRIORITY_HIGH
2016-11-21 15:01:39.374 GCD_demo[2173:386624] DISPATCH_QUEUE_PRIORITY_BACKGROUND
说明:
并行队列不是按优先级执行的,而是随机的。但是同等级的队列是按FIFO执行的。
*/
/* 了解:
名称 Dispatch Queue种类 说明
Main Dispatch Queue Serial Dispatch Queue 主线程执行
DISPATCH_QUEUE_PRIORITY_HIGH Concurrent Dispatch Queue 高优先级
DISPATCH_QUEUE_PRIORITY_DEFAULT Concurrent Dispatch Queue 默认优先级
DISPATCH_QUEUE_PRIORITY_LOW Concurrent Dispatch Queue 低优先级
DISPATCH_QUEUE_PRIORITY_BACKGROUND Concurrent Dispatch Queue 后台执行
*/
}
#pragma mark 等待所有的队列执行完毕后在执行
-(void)waitAllQueueStop{
/* 创建并行队列*/
dispatch_queue_t concurrentQueue = dispatch_queue_create("com.zsj", DISPATCH_QUEUE_CONCURRENT);
/* 创建队列组*/
dispatch_group_t groupQueue = dispatch_group_create();
/* 添加多个执行任务*/
dispatch_group_async(groupQueue,concurrentQueue , ^{
NSLog(@"组在执行中");
});
dispatch_group_async(groupQueue,concurrentQueue , ^{
for (unsigned int i = 0; i<5; i++) {
NSLog(@"我在执行123");
}
});
dispatch_group_async(groupQueue,concurrentQueue , ^{
for (unsigned int i = 0; i<3; i++) {
NSLog(@"我在执行3");
}
});
dispatch_group_wait(groupQueue, DISPATCH_TIME_FOREVER);
NSLog(@"我是组内队列执行完毕的结果");
/* 输出:
2016-11-21 15:25:33.937 GCD_demo[2265:469653] 组在执行中
2016-11-21 15:25:33.937 GCD_demo[2265:469650] 我在执行123
2016-11-21 15:25:33.941 GCD_demo[2265:469658] 我在执行3
2016-11-21 15:25:33.942 GCD_demo[2265:469650] 我在执行123
2016-11-21 15:25:33.942 GCD_demo[2265:469658] 我在执行3
2016-11-21 15:25:33.942 GCD_demo[2265:469650] 我在执行123
2016-11-21 15:25:33.942 GCD_demo[2265:469658] 我在执行3
2016-11-21 15:25:33.943 GCD_demo[2265:469650] 我在执行123
2016-11-21 15:25:33.943 GCD_demo[2265:469650] 我在执行123
2016-11-21 15:25:33.943 GCD_demo[2265:469502] 我是组内队列执行完毕的结果
*/
}
#pragma mark 线程同步函数
-(void)queueSynchronous{
/* 举例:
我们模拟,投票情况,就是现在我们假设就剩余三个票就到停止时间,下面可能会有不只3个没有投票的。
现在就是要处理这种情况。
*/
dispatch_semaphore_t signal;
signal = dispatch_semaphore_create(1);
__block long x = 0;
__block long y = 0;
__block long z = 0;
__block long u = 0;
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
NSLog(@"第一个投票的用户");
x=dispatch_semaphore_signal(signal);
sleep(1);
NSLog(@"第二个投票的用户");
y= dispatch_semaphore_signal(signal);
sleep(2);
NSLog(@"第三个投票的用户");
z = dispatch_semaphore_signal(signal);
u = dispatch_semaphore_signal(signal);
});
x = dispatch_semaphore_wait(signal, DISPATCH_TIME_FOREVER);
NSLog(@"投票处理_x:%ld",x);
y = dispatch_semaphore_wait(signal, DISPATCH_TIME_FOREVER);
NSLog(@"投票处理_y:%ld",y);
z = dispatch_semaphore_wait(signal, DISPATCH_TIME_FOREVER);
NSLog(@"投票处理_z:%ld",z);
NSLog(@"观众投票停止");
/* 这里是停止,投票计数*/
signal = dispatch_semaphore_create(0);
u = dispatch_semaphore_wait(signal, DISPATCH_TIME_FOREVER);
NSLog(@"投票处理_u:%ld",u);
/* 输出
2016-11-21 16:26:52.212 GCD_demo[2606:625907] 第一个投票的用户
2016-11-21 16:26:52.212 GCD_demo[2606:625874] 投票处理_x:0
2016-11-21 16:26:52.212 GCD_demo[2606:625874] 投票处理_y:0
2016-11-21 16:26:53.256 GCD_demo[2606:625907] 第二个投票的用户
2016-11-21 16:26:53.256 GCD_demo[2606:625874] 投票处理_z:0
2016-11-21 16:26:53.256 GCD_demo[2606:625874] 观众投票停止
*/
/*
了解:
long dispatch_semaphore_wait(dispatch_semaphore_t dsema, dispatch_time_t timeout);
这个函数会使传入的信号量dsema的值减1;这个函数的作用是这样的,如果dsema信号量的值大于0,该函数所处线程就继续执行下面的语句,并且将信号量的值减1;如果desema的值为0,那么这个函数就阻塞当前线程等待timeout(注意timeout的类型为dispatch_time_t,不能直接传入整形或float型数),如果等待的期间desema的值被dispatch_semaphore_signal函数加1了,且该函数(即dispatch_semaphore_wait)所处线程获得了信号量,那么就继续向下执行并将信号量减1。如果等待期间没有获取到信号量或者信号量的值一直为0,那么等到timeout时,其所处线程自动执行其后语句。
*/
}
#pragma mark 并行队列插入其他事件
-(void)queueInsertEvent{
dispatch_queue_t concurrentQueue = dispatch_queue_create("com.ss", DISPATCH_QUEUE_CONCURRENT);
dispatch_async(concurrentQueue, ^{
NSLog(@"插入队列处理1");
});
dispatch_async(concurrentQueue, ^{
NSLog(@"插入队列处理2");
});
/* 我们要处理其他事件*/
dispatch_barrier_async(concurrentQueue, ^{
NSLog(@"插入队列的处理事件");
});
dispatch_async(concurrentQueue, ^{
NSLog(@"插入队列处理3");
});
dispatch_async(concurrentQueue, ^{
NSLog(@"插入队列处理4");
});
/* 输出:
2016-11-21 16:45:57.431 GCD_demo[2678:693089] 插入队列处理1
2016-11-21 16:45:57.431 GCD_demo[2678:693086] 插入队列处理2
2016-11-21 16:45:57.432 GCD_demo[2678:693086] 插入队列的处理事件
2016-11-21 16:45:57.432 GCD_demo[2678:693086] 插入队列处理3
或
2016-11-21 16:47:11.508 GCD_demo[2704:697160] 插入队列处理2
2016-11-21 16:47:11.508 GCD_demo[2704:697155] 插入队列处理1
2016-11-21 16:47:11.509 GCD_demo[2704:697155] 插入队列的处理事件
2016-11-21 16:47:11.509 GCD_demo[2704:697155] 插入队列处理3
2016-11-21 16:47:11.509 GCD_demo[2704:697160] 插入队列处理4
*/
}
#pragma mark 延时处理
-(void)afterQueue{
NSLog(@"我是延时前测试");
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(3.0 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
NSLog(@"我是延时后的测试");
});
/* 输出:
2016-11-21 17:05:30.887 GCD_demo[2814:767071] 我是延时前测试
2016-11-21 17:05:34.177 GCD_demo[2814:767071] 我是延时后的测试
解释:
1.不是一定时间后执行相应的任务,而是一定时间后,将执行的操作加入到队列中(队列里面再分配执行的时间)
2.主线程 RunLoop 1/60秒检测时间,追加的时间范围 3s~(3+1/60)s
*/
}
#pragma mark 设置队列上下文
-(void)contextQueue{
/* 创建一个并行队列*/
dispatch_queue_t queue = dispatch_queue_create("com.test", DISPATCH_QUEUE_CONCURRENT);
/* 创建上下文的内容*/
Data *myData = malloc(sizeof(Data));
myData->number = 110;
/* 设置对列的上下文*/
dispatch_set_context(queue,myData);
/* 设置释放上下文的函数*/
dispatch_set_finalizer_f(queue, finalizer);
/* 我们使用对列*/
dispatch_async(queue, ^{
/* 获取该对列的上下文*/
Data *data = dispatch_get_context(queue);
NSLog(@"我是上下文:%d",data->number);
});
}
- (void)didReceiveMemoryWarning {
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
@end