iOS NSThreadGCD 线程与队列(二)

//
//  GCD_ViewController.m
//  ZM_NSThreadGCD
//
//  Created by ZM on 2015/2/9.
//  Copyright © 2015 ZM. All rights reserved.
//

#import "GCD_ViewController.h"
#import
"BaseHeader.h"

@interface GCD_ViewController ()

@end

@implementation GCD_ViewController

- (
void )viewDidLoad {
    [
super viewDidLoad ];
   
self . title = @"GCD_VC" ;
   
   
NSString *title= @"" ;
   
CGFloat width = 120 ;
   
for ( int i= 1 ; i< 11 ; i++) {
       
        title = [
NSString stringWithFormat : @"case%d" ,i];
        [
self addBtnTitle :title frame : CGRectMake ( 10 , 50 + ( 35 + 10 )*i, width, 35 ) Tag :i];
    }
   
   
CGFloat yy = SSHEIGHT - 90 ;
    [
self addBtnTitle : @"attentionCase3_1" frame : CGRectMake ( 10 , yy, width, 35 ) Tag : 111 ];
    [
self addBtnTitle : @"attentionCase3_2" frame : CGRectMake ( 10 * 2 +width, yy, width, 35 ) Tag : 222 ];
    [
self addBtnTitle : @"solveCase3_1" frame : CGRectMake ( 10 , yy+ 45 , width, 35 ) Tag : 333 ];
   
   
   
}
- (
void )myBtnClick:( UIButton *)Btn{
   
   
if (Btn. tag == 1 ) {       [ self case1 ];
    }
else if (Btn. tag == 2 ) { [ self case2 ];
    }
else if (Btn. tag == 3 ) { [ self case3 ];
    }
else if (Btn. tag == 4 ) { [ self case4 ];
    }
else if (Btn. tag == 5 ) { [ self case5 ];
    }
else if (Btn. tag == 6 ) { [ self case6 ];
    }
else if (Btn. tag == 7 ) { [ self case7 ];
    }
else if (Btn. tag == 8 ) { [ self case8 ];
    }
else if (Btn. tag == 9 ) { [ self case9 ];

    }
   
   
if (Btn. tag == 111 ) {       [ self attentionCase3_1 ];
    }
else if (Btn. tag == 222 ) { [ self attentionCase3_2 ];
    }
else if (Btn. tag == 333 ) { [ self solveCase3_1 ];
    }
}

/**
 * 
以下 4 GCD 方法的区别:
 dispatch_async         
异步任务
 dispatch_sync          
同步任务
 dispatch_barrier_async 
为异步执行调度队列:提交一个路障
 dispatch_barrier_sync  
为同步执行调度队列:提交一个路障
 
 dispatch_get_main_queue   
主队列
 dispatch_queue_t          
并行队列
 dispatch_get_global_queue 
全局并行队列
 
 */

// 例一: dispatch_sync 同步任务 提交 Block 主线程 中执行
- (
void )case1 {
   
   
dispatch_queue_t queue1 = dispatch_queue_create ( " 并行 " , DISPATCH_QUEUE_CONCURRENT );
   
dispatch_sync (queue1, ^{
       
NSLog ( @"%@" ,[ NSThread currentThread ]);  // 输出结果: {number = 1, name = main}
       
    });
}

// 例二: dispatch_async 异步任务 提交 Block 分线程 中执行
- (
void )case2 {
   
   
dispatch_queue_t queue1 = dispatch_queue_create ( " 并行 " , DISPATCH_QUEUE_CONCURRENT );
   
dispatch_async (queue1, ^{
       
NSLog ( @"%@" ,[ NSThread currentThread ]);  // 输出结果: {number = 3, name = (null)}
       
    });
}


// 例三:我们分别用 sync async 向主队列提交 Block ,结果 Block 都是在主线程中执行:
- (
void )case3 {
   
   
// 我们用 sync 如下的方式去提交 Block
   
dispatch_queue_t queue1 = dispatch_queue_create ( " 并行 " , DISPATCH_QUEUE_CONCURRENT );
   
dispatch_async (queue1, ^{
       
dispatch_sync ( dispatch_get_main_queue (), ^{
           
NSLog ( @"%@" ,[ NSThread currentThread ]);  // 输出结果: {number = 1, name = main}
        });
    });
   
}
// 注意 3_1 :在主线程 不能用 sync (同步)提交 Block 执行任务,否则会引起死锁:
- (
void )attentionCase3_1 {
   
   
   
dispatch_sync ( dispatch_get_main_queue (), ^{
       
NSLog ( @" 任务一 " );
    });
   
NSLog ( @" 任务二 " );
   
// 因为往 queue 中提交 Block ,总是追加在队列尾部的,而 queue 执行 Block 的顺序为先进先出( FIFO ),所以任务一需要在当前队列它之前的任务(任务二)全部执行完,才能轮到它。
   
// 任务一等待任务二完成,任务二等待任务一完成,相互等待 _ 被阻塞,程序被死锁在这了
}
// 注意 3_2 :在主线程 能用 async (异步)提交 Block 执行任务
- (
void )attentionCase3_2 {
   
   
dispatch_async ( dispatch_get_main_queue (), ^{
       
NSLog ( @"%@" ,[ NSThread currentThread ]);  // 输出结果: {number = 1, name = main}
    });
}

// 解决 3_1 问题
- (
void )solveCase3_1 {
   
   
// 全局并行队列
   
// 这应该是唯一一个并行队列, 只要是并行任务一般都加入到这个队列。这是系统提供的一个并发队列。
   
// 因为全局队列和主队列是两个队列,所以任务一的执行,并不需要等待任务二。
   
dispatch_sync ( dispatch_get_global_queue ( 0 , 0 ), ^{
       
NSLog ( @" 任务一 " );
    });
   
NSLog ( @" 任务二 " );
}


// 例四: 建立栅栏 _ 执行任务 dispatch_barrier_async
- (
void )case4 {
   
dispatch_queue_t queue = dispatch_queue_create ( "queue" , DISPATCH_QUEUE_CONCURRENT );
   
dispatch_async (queue, ^{
       
NSLog ( @" 任务 1" );
    });
   
dispatch_async (queue, ^{
       
NSLog ( @" 任务 2" );
    });
   
dispatch_async (queue, ^{
       
NSLog ( @" 任务 3" );
    });
   
   
// 建立栅栏 _ 执行任务 dispatch_barrier_async
   
dispatch_barrier_async (queue, ^{
       
NSLogline ( @"\n  %@\n  %@\n  %@" ,
                 
@" 任务 1 2 3 的顺序不一定 " ,
                 
@" 任务 4_ 在中间 " ,
                 
@" 最后是 5 6 7 8 9 任务顺序不一定 " );
    });
   
   
dispatch_async (queue, ^{
       
NSLog ( @" 任务 5" );
    });
   
dispatch_async (queue, ^{
       
NSLog ( @" 任务 6" );
    });
   
dispatch_async (queue, ^{
       
NSLog ( @" 任务 7" );
    });
   
dispatch_async (queue, ^{
       
NSLog ( @" 任务 8" );
    });
   
dispatch_async (queue, ^{
       
NSLog ( @" 任务 9" );
    });
   
// 结论: dispatch_barrier_async 它的作用可以用一个词概括--承上启下,它保证此前的任务都先于自己执行,此后的任务也迟于自己执行。当然它的作用导致它只有在并行队列中有意义。
   
   
// 注意:当然这里有一点需要注意的是: dispatch_barrier_(a)sync 只在自己创建的并发队列上有效,在全局 (Global) 并发队列、串行队列上,效果跟 dispatch_(a)sync 效果一样。
   
   
//3)dispatch_barrier_sync 这个方法和 dispatch_barrier_async 作用几乎一样,都可以在并行 queue 中当做栅栏。
   
// 唯一的区别就是: dispatch_barrier_sync GCD sync 共有特性,会阻塞提交 Block 的当前线程,而 dispatch_barrier_async 是异步提交,不会阻塞。
}


// 例五:例如我们在一个读写操作中 , 我们就可以如下使用:
- (
void )case5 {
   
   
// 一个读写操作中:我们要知道一个数据,读与读之间是可以用线程并行的,但是写与写、写与读之间,就必须串行同步或者使用线程锁来保证线程安全。但是我们有了 dispatch_barrier_async
   
   
dispatch_queue_t queue = dispatch_queue_create ( "queue" , DISPATCH_QUEUE_CONCURRENT );
   
dispatch_async (queue, ^{
       
NSLog ( @" 读操作 _1" );
    });
   
dispatch_async (queue, ^{
       
NSLog ( @" 读操作 _2" );
    });
   
dispatch_barrier_async (queue, ^{
       
NSLog ( @" 写操作 _1" );
    });
   
dispatch_barrier_async (queue, ^{
       
NSLog ( @" 写操作 _2" );
    });
   
dispatch_async (queue, ^{
       
NSLog ( @" 读操作 " );
    });
   
// 结论:这样写操作的时候,始终只有它这一条线程在进行。而读操作一直是并行的。这么做充分利用了多线程的优势,还不需要加锁,减少了相当一部分的性能开销。实现了读写操作的线程安全。
   
// 读与读 : 线程并行
   
// 写与写、写与读 : 必须串行同步或者使用线程锁

}


// 例六: 4 dispatch_sync ,我们来讲讲它和 dispatch_barrier_sync 的区别。二者因为是 sync 提交,所以都是阻塞当前提交 Block 线程。
      
// 而它俩唯一的区别是: dispatch_sync 并不能阻塞并行队列。其实之前死锁有提及过,担心大家感觉疑惑,还是写个例子:
- (
void )case6 {
   
dispatch_queue_t queue = dispatch_queue_create ( " 并行 " , DISPATCH_QUEUE_CONCURRENT );
   
// dispatch_sync
   
dispatch_sync (queue, ^{
       
dispatch_async (queue, ^{
           
NSLog ( @" 任务二 " );
        });
       
dispatch_async (queue, ^{
           
NSLog ( @" 任务三 " );
        });
       
// 睡眠 2
//        [NSThread sleepForTimeInterval:2];
       
NSLog ( @" 任务一 \n " );
    });
   
// 输出结果 : 任务三 任务二 任务一   (二、三顺序不固定,一最后,很显然,并行队列没有被 sync 所阻塞。)
}


// 例七:而 dispatch_barrier_sync 可以阻塞并行队列(栅栏作用的体现):
- (
void )case7 {
   
dispatch_queue_t queue = dispatch_queue_create ( " 并行 " , DISPATCH_QUEUE_CONCURRENT );
   
// dispatch_barrier_sync
   
dispatch_barrier_sync (queue, ^{
       
dispatch_async (queue, ^{
           
NSLog ( @" 任务二 " );
        });
       
dispatch_async (queue, ^{
           
NSLog ( @" 任务三 " );
        });
       
// 睡眠 2
//        [NSThread sleepForTimeInterval:2];
       
NSLog ( @" 任务一 " );
    });
   
// 输出结果 : 任务一 任务二 任务三 (一首先,二、三顺序不固定)
}

/**
 
同: dispatch_sync dispatch_barrier_sync  都能阻塞 主队列
 
区别: dispatch_sync 不能阻塞并行队列
       dispatch_barrier_sync
可以阻塞并行队列
 */


- (
void )case8 {
   
}
- (
void )case9 {
   
}


@end

你可能感兴趣的:(iOS)