iOS 멀티스레드 개발 - GCD(二)
이전 iOS 멀티스레드 개발 - GCD(二)에서 멀티스레드가 무엇인지, GCD와 스레드의 관계, 그리고 대기열을 만드는 방법과 간단한 사용법을 소개했습니다. 이 글에서 GCD의 고급 사용법을 중점적으로 요약하겠습니다.
dispatch 만들기queue_t 주의해야 할 문제
저희가 디스패치를 통해서...get_global_queue(long identifier, unsigned long flags);dispatch를 통해 전역 대기열 가져오기get_main_queue();홈팀 열 획득,dispatch를 통해queue_create(const char *_Nullable label,dispatch_queue_attr_t _Nullable attr);병렬 또는 직렬 큐를 만듭니다.우리가 주의해야 할 것은, 디스패치get_global_queue(long identifier, unsigned long flags);dispatch_get_main_queue();이 두 가지 방법은 모두 우리가 시스템이 이미 만든 대기열을 가져오는 것이다. 따라서 우리는 이 대기열에 대해 메모리 관리를 할 필요가 없다. 시스템은 우리가 적당한 시간에 이 대기열을 방출하는 것을 도울 것이다.
4
GCD API 사용
1. dispatch_queue_create
dispatch_queue_create(const char *_Nullable label,dispatch_queue_attr_t _Nullable attr); 이 방법은 첫 번째 파라미터가 대기열의 이름일 수도 있고, 비어 있을 수도 있지만, debug에 불리합니다.두 번째 매개변수는 대기열 유형입니다. NULL이 작성된 경우 기본값은 직렬 대기열, DISPATCH 입니다.QUEUE_CONCURRENT가 병렬 큐를 생성합니다.
//
dispatch_queue_t serialQueue = dispatch_queue_create("com.jiaxiang.serialQueue", DISPATCH_QUEUE_SERIAL);
//
dispatch_queue_t concurrentQueue1 = dispatch_queue_create("com.jiaxiang.concurrentQueue", DISPATCH_QUEUE_CONCURRENT);
이론적으로 우리는 이곳에서 임의의 여러 개의 대기열을 만들 수 있고, 여러 개의 직렬 대기열은 병렬로 실행할 수 있다.그러나 우리가 너무 많은 직렬 대기열을 사용했을 때 우리는 상응하는 직렬 라인을 만들 것이다. 너무 많은 라인 생성은 시스템 자원을 소모할 것이다.
2. Main Dispatch Queue/Global Dispatch Queue
// ,
dispatch_queue_t mainQueue = dispatch_get_main_queue();
// ,
dispatch_queue_t concurrentQueue2 = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
dispatch_get_global_queue(long identifier, unsigned long flags);첫 번째 파라미터는 대기열의 우선 순위를 지정하고, 두 번째 파라미터는 flag이며, 대부분의 시간은 0을 사용한다.우선순위는 4단계로 나뉘는데 높음부터 낮음까지 높음, 기본값, 낮음, 백그라운드 순으로 나뉜다.
#define DISPATCH_QUEUE_PRIORITY_HIGH 2
#define DISPATCH_QUEUE_PRIORITY_DEFAULT 0
#define DISPATCH_QUEUE_PRIORITY_LOW (-2)
#define DISPATCH_QUEUE_PRIORITY_BACKGROUND INT16_MIN
dispatch_queue_t mainQueue = dispatch_get_main_queue();
dispatch_queue_t serialQueue = dispatch_queue_create("com.jiaxiang.serialQueue", DISPATCH_QUEUE_SERIAL);
dispatch_sync(concurrentQueue1, ^{
//
NSLog(@"Concurrent Queue");
NSLog(@"Concurrent Queue%@",[NSThread currentThread]);
dispatch_async(mainQueue, ^{
//
NSLog(@"Main Queue");
NSLog(@"Main Queue%@",[NSThread currentThread]);
});
});
NSLog(@"Done");
NSLog(@"Done%@",[NSThread currentThread]);
위에서 사용한 이 동작을 병렬 대기열에 놓고 결과를 홈 대기열에 놓고 실행할 수 있습니다.
3.dispatch_set_target_queue
dispatch_set_target_queue(dispatch_object_t object,dispatch_queue_t _Nullable queue);이 방법은 한 대기열의 실행 우선 순위를 다른 대기열의 우선 순위로 설정합니다.첫 번째 파라미터는 우선순위를 변경하는 대기열이고, 두 번째 파라미터는 목표 우선순위 대기열이다.첫 번째 매개변수는 시스템에서 제공하는 Main Queue 및 Global Dispatch Queue가 될 수 없습니다.
// serialQueue concurrentQueue2
dispatch_queue_t serialQueue = dispatch_queue_create("com.jiaxiang.serialQueue", DISPATCH_QUEUE_SERIAL);
dispatch_queue_t concurrentQueue2 = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0);
dispatch_set_target_queue(serialQueue, concurrentQueue2);
dispatch_queue_t serialQueue1 = dispatch_queue_create("com.jiaxiang.serialQueue1", DISPATCH_QUEUE_SERIAL);
dispatch_queue_t serialQueue2 = dispatch_queue_create("com.jiaxiang.serialQueue2", DISPATCH_QUEUE_SERIAL);
dispatch_queue_t serialQueue3 = dispatch_queue_create("com.jiaxiang.serialQueue2", DISPATCH_QUEUE_SERIAL);
dispatch_queue_t serialQueue4 = dispatch_queue_create("com.jiaxiang.serialQueue3", DISPATCH_QUEUE_SERIAL);
dispatch_async(serialQueue, ^{
[NSThread sleepForTimeInterval:1.0];
NSLog(@"0");
});
dispatch_async(serialQueue1, ^{
[NSThread sleepForTimeInterval:1.0];
NSLog(@"1");
});
dispatch_async(serialQueue2, ^{
[NSThread sleepForTimeInterval:1.0];
NSLog(@"2");
});
dispatch_async(serialQueue3, ^{
[NSThread sleepForTimeInterval:1.0];
NSLog(@"3");
});
dispatch_async(serialQueue4, ^{
[NSThread sleepForTimeInterval:1.0];
NSLog(@"4");
});
위에서 만든 다섯 개의 직렬 대기열은 실행할 때 병렬 실행되며, 매번 실행할 때마다 선후 순서가 고정되지 않습니다.그런데 저희가 디스패치를 사용하면...set_target 이후 직렬 실행이 됩니다.
dispatch_queue_t serialQueue1 = dispatch_queue_create("com.jiaxiang.serialQueue1", DISPATCH_QUEUE_SERIAL);
dispatch_queue_t serialQueue2 = dispatch_queue_create("com.jiaxiang.serialQueue2", DISPATCH_QUEUE_SERIAL);
dispatch_queue_t serialQueue3 = dispatch_queue_create("com.jiaxiang.serialQueue2", DISPATCH_QUEUE_SERIAL);
dispatch_queue_t serialQueue4 = dispatch_queue_create("com.jiaxiang.serialQueue3", DISPATCH_QUEUE_SERIAL);
dispatch_set_target_queue(serialQueue1, serialQueue);
dispatch_set_target_queue(serialQueue2, serialQueue);
dispatch_set_target_queue(serialQueue3, serialQueue);
dispatch_set_target_queue(serialQueue4, serialQueue);
dispatch_async(serialQueue, ^{
[NSThread sleepForTimeInterval:1.0];
NSLog(@"0");
});
dispatch_async(serialQueue1, ^{
[NSThread sleepForTimeInterval:1.0];
NSLog(@"1");
});
dispatch_async(serialQueue2, ^{
[NSThread sleepForTimeInterval:1.0];
NSLog(@"2");
});
dispatch_async(serialQueue3, ^{
[NSThread sleepForTimeInterval:1.0];
NSLog(@"3");
});
dispatch_async(serialQueue4, ^{
[NSThread sleepForTimeInterval:1.0];
NSLog(@"4");
});
4,dispatch_after
dispatch_after(dispatch_time_t when,dispatch_queue_t queue, dispatch_block_t block);첫 번째 파라미터는 지정된 시간 후에 임무를 지정한 대기열에 추가하고, 두 번째 파라미터는 임무를 수행하는 대기열을 지정하며, 세 번째 파라미터는 추가된 임무이다.분명히 해야 할 것은 임무가 지정된 시간 이후에 집행되는 것이 아니라 임무가 지정된 시간 후에 대기열에 추가되기 때문에 임무가 집행되는 시간은 지정된 시간 이후에 집행될 가능성이 높다는 것이다.또한 이 방법은 비동기적인 작업을 수행하기 때문에 지정한 대기열이main queue일 때도 잠금 해제를 걱정할 필요가 없습니다.
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(3 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
NSLog(@"Hello");
});
NSLog(@"Done After");
5,Dispatch Group
GCD를 사용할 때, 우리는 때때로 우리가 병렬 대기열을 실행한 후에 모든 병렬 대기열의 임무를 추가해서 실행할 수 있기를 희망할 때가 있다.이때 우리는 디스패치 그룹을 사용하여 이 수요를 실현할 수 있다.
dispatch_queue_t concurrentQueue1 = dispatch_queue_create("com.jiaxiang.concurrentQueue", DISPATCH_QUEUE_CONCURRENT);
dispatch_group_t group = dispatch_group_create();
dispatch_group_async(group, concurrentQueue1, ^{
[NSThread sleepForTimeInterval:1.0];
NSLog(@"1");
});
dispatch_group_async(group, concurrentQueue1, ^{
[NSThread sleepForTimeInterval:1.0];
NSLog(@"2");
});
dispatch_group_async(group, concurrentQueue1, ^{
[NSThread sleepForTimeInterval:1.0];
NSLog(@"3");
});
dispatch_group_notify(group, dispatch_get_main_queue(), ^{
NSLog(@"Done");
});
6.dispatch_barrier_async
병렬 대기열의 1, 2, 3 이 몇 가지 임무를 수행한 후에 4를 수행한 다음에 5, 6, 7을 수행하여 데이터를 쓰는 동시에 데이터를 읽고 데이터 경쟁을 피하려면 dispatchbarrier_async.
dispatch_queue_t concurrentQueue1 = dispatch_queue_create("com.jiaxiang.concurrentQueue", DISPATCH_QUEUE_CONCURRENT);
dispatch_async(concurrentQueue1, ^{
[NSThread sleepForTimeInterval:1.0];
NSLog(@"1");
});
dispatch_async(concurrentQueue1, ^{
[NSThread sleepForTimeInterval:1.0];
NSLog(@"2");
});
dispatch_async(concurrentQueue1, ^{
[NSThread sleepForTimeInterval:1.0];
NSLog(@"3");
});
dispatch_barrier_async(concurrentQueue1, ^{
[NSThread sleepForTimeInterval:1.0];
NSLog(@"4");
});
dispatch_async(concurrentQueue1, ^{
[NSThread sleepForTimeInterval:1.0];
NSLog(@"5");
});
dispatch_async(concurrentQueue1, ^{
[NSThread sleepForTimeInterval:1.0];
NSLog(@"6");
});
dispatch_async(concurrentQueue1, ^{
[NSThread sleepForTimeInterval:1.0];
NSLog(@"7");
});
7.dispatch_apply
이 함수는 지정한 횟수에 따라 지정한 작업을 대기열에 추가하고 모든 처리가 끝날 때까지 기다립니다.
dispatch_queue_t concurrentQueue1 = dispatch_queue_create("com.jiaxiang.concurrentQueue", DISPATCH_QUEUE_CONCURRENT);
dispatch_apply(10, concurrentQueue1, ^(size_t index) {
NSLog(@"%zu",index);
});
NSLog(@"Done");
8.dispatch_suspend/dispatch_resume
dispatch_suspend (queue), 지정한 대기열을 닫습니다. 대기열에서 실행된 작업은 영향을 주지 않으며, 실행된 작업의 실행을 정지합니다.dispatch_resume (queue), 지정한 대기열을 복원하고, 대기열에서 실행된 작업을 계속 수행합니다.
9.Dispatch Semaphore
신호량을 통해 대기열의 작업 실행 상황을 제어합니다.
이 내용에 흥미가 있습니까?
현재 기사가 여러분의 문제를 해결하지 못하는 경우 AI 엔진은 머신러닝 분석(스마트 모델이 방금 만들어져 부정확한 경우가 있을 수 있음)을 통해 가장 유사한 기사를 추천합니다:
다양한 언어의 JSONJSON은 Javascript 표기법을 사용하여 데이터 구조를 레이아웃하는 데이터 형식입니다. 그러나 Javascript가 코드에서 이러한 구조를 나타낼 수 있는 유일한 언어는 아닙니다. 저는 일반적으로 '객체'{}...
텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
CC BY-SA 2.5, CC BY-SA 3.0 및 CC BY-SA 4.0에 따라 라이센스가 부여됩니다.