刚接触GCD,感觉这项技术很高大尚,学习了两天发现其也很简单,可以实现简单的异步,dispatch_async,并且可以实现一组异步操作,等到这一组操作完成之后可以利用通知来告诉我们来执行结束后的工作dispatch_group_notify,另外也可以在异步中使用dispatch_barrier来实现同步以后的操作,同时对于IO操作也提供了一系列操作的API,也就是这些API让我感觉到其难度突然之间上升了好多,在看这些接口的时候我就想到利用Group与dispatch_io_read,dispatch_io_write来进行分块数据的读写,同时在stackoverflow上查看了一些有关dispatch_io的问题,上午还感觉很好,刚才在网上看到一个例子不错,就COPY下来修改一下做一个DEMO,但是却出现了这么长时间没有出现的问题:死锁现象。代码如下:-(void)disPatchIOTest{
NSString *file=[[NSBundle mainBundle]pathForResource:@"444" ofType:@"txt"];
NSArray* files = @[file];
NSString* outFile = [[NSBundle mainBundle]pathForResource:@"333" ofType:@"txt"];
NSString* queueName = [NSString stringWithFormat:@"%@.IO", [[NSBundle mainBundle].infoDictionary objectForKey:(id)kCFBundleIdentifierKey]];
NSLog(@"the queueName is %@",queueName);
dispatch_queue_t queue = dispatch_queue_create(queueName.UTF8String, DISPATCH_QUEUE_SERIAL);
dispatch_group_t group = dispatch_group_create();
dispatch_io_t io_write = dispatch_io_create_with_path(DISPATCH_IO_STREAM, outFile.UTF8String, (O_RDWR | O_CREAT | O_APPEND), (S_IWUSR | S_IRUSR | S_IRGRP | S_IROTH), queue, NULL);
NSLog(@"%@",io_write);
dispatch_io_set_high_water(io_write, 1024*1024);
[files enumerateObjectsUsingBlock:^(NSString* file, NSUInteger idx, BOOL *stop) {
if (*stop) {
return;
}
dispatch_group_enter(group);
dispatch_io_t io_read = dispatch_io_create_with_path(DISPATCH_IO_STREAM, file.UTF8String, O_RDONLY, 0, queue, NULL);
dispatch_io_set_high_water(io_read, 1024*1024);
dispatch_io_read(io_read, 0, SIZE_MAX, queue, ^(bool done, dispatch_data_t data, int error) {
if (error || *stop) {
NSLog(@"the data is %@",data);
NSLog(@"error is %d",error);
dispatch_io_close(io_write, 0);
*stop = YES;
return;
}
if (data) {
size_t bytesRead = dispatch_data_get_size(data);
if (bytesRead > 0) {
NSLog(@"data is %@",data);
dispatch_group_enter(group);
dispatch_io_write(io_write, 0, data, dispatch_get_global_queue(0, 0), ^(bool doneWriting, dispatch_data_t dataToBeWritten, int errorWriting) {
if (errorWriting || *stop) {
dispatch_io_close(io_read, DISPATCH_IO_STOP);
*stop = YES;
dispatch_group_leave(group);
return;
}
if (doneWriting) {
dispatch_group_leave(group);
}
});
}
}
if (done) {
dispatch_io_close(io_read, 0);
if (files.count == (idx+1)) {
dispatch_io_close(io_write, 0);
}
dispatch_group_leave(group);
}
long result= dispatch_group_wait(group, DISPATCH_TIME_FOREVER);
if(result==0)
{
NSLog(@"the dispatch io is ending");
}
else{
NSLog(@"the dispatch io is not ending");
}
});
}];
NSString *file=[[NSBundle mainBundle]pathForResource:@"444" ofType:@"txt"];
NSArray* files = @[file];
NSString* outFile = [[NSBundle mainBundle]pathForResource:@"333" ofType:@"txt"];
NSString* queueName = [NSString stringWithFormat:@"%@.IO", [[NSBundle mainBundle].infoDictionary objectForKey:(id)kCFBundleIdentifierKey]];
NSLog(@"the queueName is %@",queueName);
dispatch_queue_t queue = dispatch_queue_create(queueName.UTF8String, DISPATCH_QUEUE_SERIAL);
dispatch_group_t group = dispatch_group_create();
dispatch_io_t io_write = dispatch_io_create_with_path(DISPATCH_IO_STREAM, outFile.UTF8String, (O_RDWR | O_CREAT | O_APPEND), (S_IWUSR | S_IRUSR | S_IRGRP | S_IROTH), queue, NULL);
NSLog(@"%@",io_write);
dispatch_io_set_high_water(io_write, 1024*1024);
[files enumerateObjectsUsingBlock:^(NSString* file, NSUInteger idx, BOOL *stop) {
if (*stop) {
return;
}
dispatch_group_enter(group);
dispatch_io_t io_read = dispatch_io_create_with_path(DISPATCH_IO_STREAM, file.UTF8String, O_RDONLY, 0, queue, NULL);
dispatch_io_set_high_water(io_read, 1024*1024);
dispatch_io_read(io_read, 0, SIZE_MAX, queue, ^(bool done, dispatch_data_t data, int error) {
if (error || *stop) {
NSLog(@"the data is %@",data);
NSLog(@"error is %d",error);
dispatch_io_close(io_write, 0);
*stop = YES;
return;
}
if (data) {
size_t bytesRead = dispatch_data_get_size(data);
if (bytesRead > 0) {
NSLog(@"data is %@",data);
dispatch_group_enter(group);
dispatch_io_write(io_write, 0, data, dispatch_get_global_queue(0, 0), ^(bool doneWriting, dispatch_data_t dataToBeWritten, int errorWriting) {
if (errorWriting || *stop) {
dispatch_io_close(io_read, DISPATCH_IO_STOP);
*stop = YES;
dispatch_group_leave(group);
return;
}
if (doneWriting) {
dispatch_group_leave(group);
}
});
}
}
if (done) {
dispatch_io_close(io_read, 0);
if (files.count == (idx+1)) {
dispatch_io_close(io_write, 0);
}
dispatch_group_leave(group);
}
long result= dispatch_group_wait(group, DISPATCH_TIME_FOREVER);
if(result==0)
{
NSLog(@"the dispatch io is ending");
}
else{
NSLog(@"the dispatch io is not ending");
}
});
}];
}这个问题暂且记下,我想过段时间随着知识的积累,这个问题会迎刃而解。同时也感觉到多线程的可怕之处,现阶段还是使用一些高级的API吧,至于一些简单的任务可以使用GCD,有关于IO方面的操作还是不要使用为妙,因为自己还没有操作它的能力。不过还好有CoCoa给我们提供了好多的高层接口,如NSOPerationQueue,NSstream
刚看了wwdc2015有关GCD的视频,发现其讲述了一个新的技术:Quality of Service (qos),其分为四类:UI,IN,UT,BG,其解决了对于多线程而CPU比较少时应先执行哪个线程的问题,从开发的角度来看,这样减少了程序员的工作,我们只需要在创建block时,设置相应的qos class的标识即可,如:dispatch_block_t block;
block = dispatch_block_create_with_qos_class(
0, QOS_CLASS_UTILITY, -8, ^{…});
dispatch_async(queue, block); 这样在内部由OS为我们做出最合理的选择,从面减轻我们的工作,感觉这项技术和Size Class很像。