먼저 기본적인 GCD의 기능에 대해서 알아보자.
GCD는 태스크를 저장하는 큐(디스패치큐)를 이용하여 동작하며 3종류의 큐가 정의 되어 있다.
첫번째 글에도 잠깐 언급하였지만 간단히 다시 한번 설명하자면,
직렬큐:태스크를 추가한순으로 실행되는 큐
dispatch_queue_create("jp.hateblo.shin.LABEL_NAME", NULL)
병렬큐:추가된태스크를 병렬로 실행하는 큐 (4개의 글로벌 병렬큐가 이미 준비되어있다.)
dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0)
메인큐:추가된태스크가 메인스레드에서 실행되는큐. ( UI작업은 이큐에서 동작해야함.)
큐의 취득은 dispatch_get_main_queue()
각각의 큐는 코드도 서로 다르지만 사용하는방법은 같다.
태스크에 등록할 때에는dispatch_async 나 dispatch_sync의 두가지 방법이 있다. 태스크의 등록할 시점에 동기로 실행할지 비동기일지를 지정한다.
직렬큐라면..
#import <Foundation/Foundation.h>
int main(int argc, char* argv[])
{
@autoreleasepool {
dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
dispatch_async(queue, ^{
[NSThread sleepForTimeInterval:1];
NSLog(@"Done: %d", 1);
});
dispatch_async(queue, ^{
[NSThread sleepForTimeInterval:1];
NSLog(@"Done: %d", 2);
});
// 여기서 queue에 쌓인 태스크가 전부 끝날때까지 메인스레드는 대기한다.
dispatch_sync(queue, ^{
[NSThread sleepForTimeInterval:1];
NSLog(@"Done: %d", 3);
});
}
return 0;
}
실행 결과출력.
2015-03-17 16:05:50.864 TestApp3[5693:1456773] Done: 3
2015-03-17 16:05:50.864 TestApp3[5693:1457020] Done: 1
2015-03-17 16:05:50.864 TestApp3[5693:1457019] Done: 2
병렬큐를 구현한다면..
#import <Foundation/Foundation.h>
int main(int argc, char* argv[])
{
@autoreleasepool {
dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
dispatch_async(queue, ^{
[NSThread sleepForTimeInterval:3];
NSLog(@"@Done: %d", 1);
});
dispatch_async(queue, ^{
[NSThread sleepForTimeInterval:3];
NSLog(@"@Done: %d", 2);
});
dispatch_sync(queue, ^{
[NSThread sleepForTimeInterval:3];
NSLog(@"@Done: %d", 3);
});
// 여기서 queue를 병렬처리 하고 샆다면..
}
return 0;
}
dispatch_sync를 사용함으로써 큐에 쌓인 태스크가 종료될때까지 대기하므로 메인스레드에서 별도의 처리를 할 수 없게된다.
이런경우에는 디스패치 그룹을 사용하면 된다.
#import <Foundation/Foundation.h>
int main(int argc, char* argv[])
{
@autoreleasepool {
dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
dispatch_group_t group = dispatch_group_create();
dispatch_group_async(group, queue, ^{
[NSThread sleepForTimeInterval:3];
NSLog(@"Done: %d", 1);
});
dispatch_group_async(group, queue, ^{
[NSThread sleepForTimeInterval:3];
NSLog(@"Done: %d", 2);
});
dispatch_group_async(group, queue, ^{
[NSThread sleepForTimeInterval:3];
NSLog(@"Done: %d", 3);
});
// 이지점에서 쌓인큐를 종료됨과 동시에 호출된다.
// dispatch_group_wait은 포함 되지 않는다.
dispatch_group_notify(group, queue, ^{
NSLog(@"All tasks are done!");
});
NSLog(@"do something...");
[NSThread sleepForTimeInterval:1];
NSLog(@"waiting...");
dispatch_group_wait(group, DISPATCH_TIME_FOREVER);
// 여기서 약간 기다려주지 안흥면 notify처리전에 프로그램의 끝나버리므로..약간 딜레이를
[NSThread sleepForTimeInterval:1];
}
return 0;
}
2015-03-17 16:06:22.744 TestApp3[5717:1461092] do something...
2015-03-17 16:06:23.749 TestApp3[5717:1461092] waiting...
2015-03-17 16:06:25.744 TestApp3[5717:1461228] Done: 3
2015-03-17 16:06:25.744 TestApp3[5717:1461229] Done: 2
2015-03-17 16:06:25.744 TestApp3[5717:1461232] Done: 1
2015-03-17 16:06:25.744 TestApp3[5717:1461232] All tasks are done!
dispatch_group_async를 태스크에 등록을 하면 필요할 경우에 dispatch_group_wait로 큐에 쌓인 태스크가 종료되는것을 기다릴 수 있다.
dispatch_group_notify은 옵션이지만 종료처리에 이용할 수 있다.
디스패치와 세마포어
GCD는 세마포어를 이용할 수도 있다. (세마포어란 전글에도 설명했듯이 배타제어를 위한 방법중 하나이다.)
물론 직렬큐를 잘만 이용한다면 크리티컬섹션을 이용한 세마포어가 필요없겠지만 어쨋든 직력큐와 같은 효과를 낼 수 있다.
#import <Foundation/Foundation.h>
int main(int argc, char* argv[])
{
@autoreleasepool {
dispatch_semaphore_t semaphore = dispatch_semaphore_create(0); //열쇠갯수
dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
dispatch_async(queue, ^{
[NSThread sleepForTimeInterval:2]; // do something
NSLog(@"Finish!");
dispatch_semaphore_signal(semaphore); //열쇠갯수 늘림
});
[NSThread sleepForTimeInterval:1]; // do something
NSLog(@"waiting...");
dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER); //열쇠반환될때 까지 기다림
}
return 0;
}
2015-03-17 16:06:59.677 TestApp3[5746:1465642] waiting...
2015-03-17 16:07:00.677 TestApp3[5746:1465821] Finish!
GCD에 대해선 언급한 것 이외에도 너무나도 많은 기능들이 있으니 애플문서를 참고하면 될듯하다.
'코딩(プログラミング)' 카테고리의 다른 글
[iOS]Objective-C로 GCD로 멀티스레드 구현하기(3) (4) | 2015.03.20 |
---|---|
[iOS]Objective-C로 NSOperation로 멀티스레드 구현하기(2) (0) | 2015.03.18 |
[iOS]Objective-C로 스레드 이해하기(1) (1) | 2015.03.04 |
[iOS]UIWebView를 이용하지 않는 링크라벨 구현하기 (0) | 2015.02.13 |
Objective-C에서의 output parameter 사용시 ARC 생각하기 (2) | 2015.02.02 |
[Objective-c]Parse를 이용한 앱개발 ( PFObject를 이펙티브하게 사용하기) (0) | 2015.01.17 |
댓글을 달아 주세요
검은건 글씨요 흰건 바탕페이지라....ㅠㅠ
에이 ~ 다 알면서~
병렬큐에서
dispatch_async(queue, ^{
[NSThread sleepForTimeInterval:3];
NSLog(@"@Done: %d", 2);
});
dispatch_sync(queue, ^{
[NSThread sleepForTimeInterval:3];
NSLog(@"@Done: %d", 3);
});
에서 dispatch_sync랑 dispatch_async를 다르게 준건 무슨 의도로 주신거예요?
마지막에 싱크를 안해주면 메소드가 끝나버리니까 확인이 안되잖어. 그래서 동기로 3초준거지