制御GCD同時スレッド数

2422 ワード

Grand Central Dispatch(GCD)はAppleが開発したマルチコアプログラミングの新しい解決策である.マルチコアプロセッサや他の対称マルチプロセッサシステムをサポートするために、主にアプリケーションを最適化するために使用されます.これは、iOS 4以降で使用できるオンライン・スレッド・プール・モードに基づいて実行される同時タスクです.
GCDは、デュアルコア、クアッドコアなど、より多くのCPUコアを自動的に利用します.しかし、パラレルqueueが多すぎる場合があり、オープンスレッドが多すぎる可能性があります.以下にThreadManagerがカプセル化され、下位レベルでもGCDが呼び出されますが、同時スレッドの数は制御されます.実現原理は非常に簡単である.ThreadManagerにはasynBlockメソッドがあり、asynBlockメソッドはいくつかのblockを常駐スレッドに非同期化します.非同期常駐スレッドにはBlock,dispatch_を維持する配列があります.semaphore_tはスレッドの同時数を制御する.
@interface ThreadManager ()

@property (atomic, strong) NSLock *lock;
@property (nonatomic, strong) dispatch_semaphore_t semaphore;
@property (nonatomic, strong) NSMutableArray *blocks;
@property (nonatomic, strong) NSThread *thread;

@end

@implementation ThreadManager

+ (instancetype)shareInstance{
    static dispatch_once_t onceToken;
    static ThreadManager *manager = nil;
    dispatch_once(&onceToken, ^{
        manager = [ThreadManager new];
    });
    return manager;
}

- (instancetype)init{
    if (self = [super init]) {
        //5 not 6
        _semaphore = dispatch_semaphore_create(5);
        _lock = [[NSLock alloc] init];
        _blocks = [NSMutableArray array];
        _thread = [[NSThread alloc] initWithTarget:self selector:@selector(testRun) object:nil];
        [_thread start];
    }
    return  self;
}

- (void)testRun{
    [[NSRunLoop currentRunLoop] addPort:[NSPort port] forMode:NSDefaultRunLoopMode];
    [[NSRunLoop currentRunLoop] run];
}

- (void)asynBlock:(dispatch_block_t)block{
    NSLog(@"asynBlock begin");
    [self.lock lock];
    [_blocks addObject:block];
    [self.lock unlock];
    
    [self performSelector:@selector(excuteBlock) onThread:self.thread withObject:nil waitUntilDone:NO];

    NSLog(@"asynBlock block end");
    

}


- (void)excuteBlock{
    [self.lock lock];
    if (_blocks.count > 0) {
        dispatch_block_t block = [_blocks firstObject];
        [_blocks removeObjectAtIndex:0];
        [self doBlock:block];
    }
    [self.lock unlock];
}

- (void)doBlock:(dispatch_block_t)block{
    dispatch_semaphore_wait(self.semaphore, DISPATCH_TIME_FOREVER);
//    [NSThread detachNewThreadWithBlock:^{
//        block();
//        dispatch_semaphore_signal(self.semaphore);
//    }];
    dispatch_async(dispatch_get_global_queue(0, 0), ^{
        block();
        dispatch_semaphore_signal(self.semaphore);
    });
}

@end