Grand Central Dispatch(GCD)는 큐를 동기/비동기로 처리할수 있도록 도와주는 도구다. 쓰레드를 os 가 자동관리 및 분배해준다. 개발자는 큐에 태스크를 생성해서 넣어주면 OS가 자동으로 태스크들을 실행해주는 방식이다.
일단 자바의 쓰레드에 비해 사용하기 쉽다는 거다.
(처리블럭)을 이용하여 콜백함수처럼 사용하는 블럭코딩은 다음과 같이 한다.
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view.
UBPayInterface *interface = [UBPayInterface sharedInstance:FALSE];
BOOL isInitialized = [interface isInitalized1];
//---- 1.선언방식
^{
NSLog(@"I am Block");
};;
// 변수에 대입방법
void (^myBlock)(void) = ^{
NSLog(@"This is a Block");
};
// 사용
myBlock();
//---- 2.변수에 파라메터와 리턴값
// 리턴값 (^변수이름)(파라메터들) = ^(파라메터들) { 리턴값 } 형식이다.
NSString* (^getParameterAndReturnString)(NSString*, BOOL) = ^(NSString* name, BOOL isTrush){
NSString* helloYour = nil;
if (!isTrush) {
helloYour = [NSString stringWithFormat:@"%@, is a Liar", name];
}
return helloYour;
};
// 사용
NSLog(@"%@", getParameterAndReturnString(@"kim", FALSE));
//---- 3.블럭은 {} 스코프안에서 처리되기 때문에 외부의 변수를 기본적으로 읽을수 없다. 때문에 __block 키워드를 사용하여 블럭스코프외부의 변수에 제한적으로 접근할수 있다.
__block int outerVal = 100;
void (^canReadableOuterVal)(void) = ^(void){
outerVal = 50;
};
// 사용
canReadableOuterVal();
NSLog(@"%d", outerVal);
//---- 4.2 호출할때는 선언된 파라메터와 같은 형식으로 호출하면 된다.
//Java 인터페이스라면 useBlockParameterEx(new myInterface() { @Override sumSum(int num1, int num2) {NSLog(@"%d", num1 + num2);} })
[self useBlockParameterEx:^(int num1, int num2) {
NSLog(@"%d", num1 + num2);
}];
NSLog(@"%@", isInitialized ? @"초기화 성공" : @"초기화 실패" );
}
//---- 4.1 함수의 파라메터로 선언은 이렇게 한다.(람다처럼)
//Java 인터페이스라면 useBlockParameterEx(MyInterface argMyinterface) { argMyinterface.sumSum(10, 20); }
- (void) useBlockParameterEx: (void (^)(int, int)) sumSum {
sumSum(10, 20);
}
Dispatch Queues 디스패치큐 .
디스패치큐는 dispatch_get_main_queue(프로그램에서 사용하는 메인큐 싱글, 즉 시리얼 디스패치큐) 와 dispatch_get_global_queue(시스템에서 사용하는 동시성 큐, 콘커런트 큐) 와 프로그래머 직접 만드는 dispatch_queue_create(이 명령으로 쓰레드를 프로그래머만든다)
이렇게 3종류가 있다.
순차적으로 실행해야 되는 작업은 DISPATCH_QUEUE_SERIAL옵션으로 큐를 만들고 , 작업을 큐에 넣으면 된다.
sync - 릴레이 처럼 출발한 순서대로 //---- 5. Serial 큐.
dispatch_queue_t queue = dispatch_queue_create("test", DISPATCH_QUEUE_SERIAL);
dispatch_sync(queue, ^{ NSLog(@"-> 1"); });
dispatch_sync(queue, ^{ NSLog(@"-> 2"); });
dispatch_sync(queue, ^{ NSLog(@"-> 3"); });
//---- 5-1. Serial 큐 지연시키기.
dispatch_time_t pushTime3s = dispatch_time(DISPATCH_TIME_NOW, (int64_t)(3.0 * NSEC_PER_SEC));
dispatch_sync(queue, ^{ NSLog(@"-> 5"); });
dispatch_after(pushTime3s,queue, ^{ NSLog(@"-> 6"); });
//---- 5-2. Serial 큐 지연시키기.
// 일단 블럭시키고 시간이 걸리는 작업을 하자 8->6 이 예상되지만, 블럭킹처리시간으로 인해 큐에 추가되는 순서는 6->8
// 시간지연을 주더라도 해당시간에 실행되는것이아니라 해당시간에 큐에 추가하려고 하는거다.
// 따라서 긴시간 작업하던 7의 중간에 6이 끼어들어추가하려해서 추가됬고, 8이 그다음에 추가된거다.주의해야한다.
typedef void (^iambloking)(void);
iambloking blokinghehe = ^{
NSMutableArray *array = [[NSMutableArray alloc] init];
for ( long i = 0; i < 100000000; i++ ) {
[array addObject:[NSNumber numberWithLong:i]];
}};
dispatch_sync(queue, ^{ NSLog(@"-> 7");blokinghehe(); }); // 오래걸리는 블럭킹을 부르자
dispatch_sync(queue, ^{ NSLog(@"-> 8"); });
//1,2,3,4,5,7(wait),6,8
Async - 마라톤처럼 도착한 순서대로
//---- 5. Serial 큐.
dispatch_queue_t queue = dispatch_queue_create("test", DISPATCH_QUEUE_SERIAL);
dispatch_async(queue, ^{ NSLog(@"-> 1"); });
dispatch_async(queue, ^{ NSLog(@"-> 2"); });
dispatch_async(queue, ^{ NSLog(@"-> 3"); });
//---- 5-1. Serial 큐 지연시키기.
dispatch_time_t pushTime3s = dispatch_time(DISPATCH_TIME_NOW, (int64_t)(3.0 * NSEC_PER_SEC));
dispatch_async(queue, ^{ NSLog(@"-> 5"); });
dispatch_after(pushTime3s,queue, ^{ NSLog(@"-> 6"); });
//---- 5-2. Serial 큐 지연시키기.
// 일단 블럭시키고 시간이 걸리는 작업을 하자 8->6 이 예상되지만, 블럭킹처리시간으로 인해 큐에 추가되는 순서는 6->8
// 시간지연을 주더라도 해당시간에 실행되는것이아니라 해당시간에 큐에 추가하려고 하는거다.
// 따라서 긴시간 작업하던 7의 중간에 6이 끼어들어추가하려해서 추가됬고, 8이 그다음에 추가된거다.주의해야한다.
typedef void (^iambloking)(void);
iambloking blokinghehe = ^{
NSMutableArray *array = [[NSMutableArray alloc] init];
for ( long i = 0; i < 100000000; i++ ) {
[array addObject:[NSNumber numberWithLong:i]];
}};
dispatch_async(queue, ^{
NSLog(@"-> 7");
dispatch_async(dispatch_queue_create("innerQ", DISPATCH_QUEUE_SERIAL), ^{ NSLog(@"-> innerQ"); blokinghehe(); });
}); // 오래걸리는 블럭킹을 부르자
dispatch_async(queue, ^{ NSLog(@"-> 8"); });
//1,2,3,4,5,7(wait),8,6
B. Concurrent Dispatch Queue 생성
동시에 여러 태스크를 동시다발적으로 실행할수 있다. SERIAL은 한번에 한개의 태스크가 끝나야 다음 태스크로 넘어갔지만, CONCURRENT에서는 전역쓰레드의 여유에 따라서 태스크들이 순서에 상관없이 실행될수있다. 각 태스트는 각자으 ㅣ쓰레드를 생성하여 수행된다.
사용법은 SERIAL과 같다.