多线程编程-NSObject、NSThread、NSOperation和NSOperationQueue、GCD

本文深入探讨了GCD的基本概念与应用技巧,包括主队列与全局队列的特点及使用方法,并介绍了自定义队列的创建与管理。此外,还详细解析了NSObject、NSThread以及NSOperation和NSOperationQueue在多线程编程中的具体应用。
1.
    NSArray *array = @[@1,@2,@3];
    
    //数组排序:
    //NSSortStable:串行,在排序执行的时候,程序为顺序结构执行,排序不执行完成,后面的代码不会执行。(耗时间,但是结果安全)
    //NSSortConcurrent:并行,在程序执行的时候,程序为多线程方式,排序方式执行的时候,下面的代码页同步执行。(节省时间,结果不安全)
    
    //数组排序
    [array sortedArrayWithOptions:NSSortStable usingComparator:^NSComparisonResult(id obj1, id obj2) {
        return  [obj1 compare:obj2];
    }];
    
    NSLog(@"%@",array);
    

#pragma mark------------BOOL和bool的区别
//    bool :非0即为真,只占8位,超过127或-128会出错
    bool i = 1;
    NSLog(@"bool:%d",i);

   

2.
//定义一个无返回值,有参的函数
void function(void *name);

void function(void *name)
{
    NSLog(@"%s",name);
}

@interface ViewController ()

@end

@implementation ViewController

- (void)viewDidLoad {
    [super viewDidLoad];
 
    
#pragma mark--------------GCD
    
    
    //主对列和全局队列都是单例,主对列串行,全局队列并行。
    
    //1.主队列:主对列是串行队列,只要在主对列中的线程都是主线程
    //2.全局队列:全局队列是并行队列
    //3.自定义队列(串行队列,并行队列)

    
    
#pragma mark---------------主对列
     /*
    //dispatch_queue_t:获取GCD中所有的队列(主对列和子队列都用这个类型,相当于int)
    
    
   #pragma mark--------------获取现在线程(number,name)
        //注意:只要number不是1,都是子线程,number的值表示优先级。
        NSLog(@"%@",[NSThread currentThread]);
    
    
    //获取主对列
   dispatch_queue_t mainQueue = dispatch_get_main_queue();
    
    //向主对列中添加任务
    dispatch_async(mainQueue, ^{
        NSLog(@"第一个任务........");
    });

    dispatch_async(mainQueue, ^{
        NSLog(@"第二个任务.........");
    });
    
    dispatch_async(mainQueue, ^{
        NSLog(@"第三个任务.........");
    });
    
    */
    
    
    
    
    
    
    //设置延时执行:注意:不要给主对列中加延时器,一般放在并行队列中
    
    //方法一:
//    dispatch_time_t time = dispatch_time(DISPATCH_TIME_NOW, (int64_t)(10*NSEC_PER_SEC));
//    dispatch_after(time, mainQueue, ^{
//        NSLog(@"延时任务............");
//    });
    
    //方法二:(直接用代码块)
//    dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(10 * NSEC_PER_SEC)),mainQueue, ^{
//        NSLog(@"延时任务...........");
//    });
    
    
    
    
    
#pragma mark-----------------全局队列(并行队列)
 /*
    //获取全局队列
    dispatch_queue_t globalQueue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT,0);
    
    //向队列中添加任务
    dispatch_async(globalQueue, ^{
        NSLog(@"wo≈ˆang");
    });
    dispatch_async(globalQueue, ^{
        NSLog(@"碎觉觉");
        
        
    });
    dispatch_async(globalQueue, ^{
        NSLog(@"333333333333");
    });
    
    //重复执行多次
        size_t times = 3;
        dispatch_apply(times,  globalQueue , ^(size_t t) {
            NSLog(@"哇哈哈哈哈哈哈,%zu",t);
        });

    
    //创建一个分组并添加任务
    dispatch_group_t group = dispatch_group_create();
    
    
    //和添加在队列的位置有关系,当处于队列末尾的时候,最后执行
    dispatch_group_notify(group, globalQueue, ^{
        NSLog(@"我是最后一个噢噢噢噢");
    });
    
    
    //添加任务
    dispatch_group_async(group, globalQueue, ^{
        NSLog(@"第一个分组第一小队");
    });
    
   

    
    dispatch_group_async(group, globalQueue, ^{
        NSLog(@"第一个分组第二小队");
    });
    dispatch_group_async(group, globalQueue, ^{
        NSLog(@"第一个分组第三小队");
    });
    */
 
    
    
#pragma mark----------------自定义队列
    
    //1.自定义串行队列
    //第一个参数:队列标识符,可以获取到某一队列的标识符
    //第二个参数:队列的类型(串行或者并行)
    /*
    dispatch_queue_t serialQueue = dispatch_queue_create("serial", DISPATCH_QUEUE_SERIAL);
    
    //添加任务(task)
    dispatch_async(serialQueue, ^{
        NSLog(@"第一个任务");
    });
    dispatch_async(serialQueue, ^{
        NSLog(@"第二个任务");
    });
    dispatch_async(serialQueue, ^{
        NSLog(@"第三个任务");
    });
    
    //获取队列的标识符
   const char *name = dispatch_queue_get_label(serialQueue);
    NSLog(@"%s",name);
    
    */
    
    
    
    
    
   //2.自定义并行队列
    //创建并行队列
    dispatch_queue_t concurrentQueue = dispatch_queue_create("concurrent", DISPATCH_QUEUE_CONCURRENT);
    
    //添加task
    dispatch_async(concurrentQueue, ^{
        NSLog(@"第一个任务");
    });
    
    //前提:该方法必须在自定义的并行队列中才有用,系统的不好使
    
   //将任务添加到并行队列中,必须等barrier中的任务执行完成后再执行下面的任务
    dispatch_barrier_async(concurrentQueue, ^{
        
        int sum = 0;
        for (int i = 0; i < 63500000; i++) {
            sum += i;
        }
        
        NSLog(@"执行完成,sum=%d",sum);
        
    });

    
    
    dispatch_async(concurrentQueue, ^{
        NSLog(@"第二个任务");
    });
    
    
    
    //将任务添加到队列中,必须等sync里面的block代码执行完成,才执行下面的代码.
    dispatch_sync(concurrentQueue, ^{
        int sum = 0;
        for (int i = 0; i < 63500000; i++) {
            sum += i;
        }
        
        NSLog(@"等我哦,sum=%d",sum);
        
        
    });
    
    
    dispatch_async(concurrentQueue, ^{
        NSLog(@"第三个任务");
    });
    
    
    //GCD可以使用此函数,向队列中添加函数,让函数执行。
    //函数类型:void (*)(void *):任何指针类型的参数,无返回值的函数
//    void * :任何类型的指针类型
    
    //第二个参数:函数的参数(要传入函数的实参)
    //第三个参数:自定义的函数名
    dispatch_async_f(concurrentQueue, "string", function);
    

    
    //dispatch_once 添加的任务 在整个程序运行期间只会执行一次(重复执行无效)
    static dispatch_once_t onceToken;
    
    dispatch_once(&onceToken, ^{
        NSLog(@"哈哈哈哈哈哈");
    });
 
    dispatch_once(&onceToken, ^{
        NSLog(@"哈哈哈哈哈哈");

    });
    
    dispatch_once(&onceToken, ^{
        NSLog(@"哈哈哈哈哈哈");
        
    });

}




3.#pragma mark--------------NSObject 多线程方式(二)
    
    
//withObject:是传参使用,不需要传参,则可写成nil,要使用参数,则可写成参数
    
    //NSObject 多线程方式
//    [self performSelectorInBackground:@selector(calculate) withObject:@"参数"];

-(void)calculate:(id)sender
{
#warning mark-------------子线程中必须要写自动释放池,否则程序容易crash掉
    @autoreleasepool {
        NSArray *array = @[@1,@2,@3,@4,@5];
        
        for (int i = 0; i < 10; i++) {
            array = [array arrayByAddingObjectsFromArray:array] ;
        }
        
        self.view.backgroundColor = [UIColor cyanColor];
        
        NSLog(@"---------sender = %@",sender);
        
        
#pragma mark--------------判断该线程是否是主线程(BOOL)
        NSLog(@"=============%d",[NSThread isMainThread]);
    }
    
  }

4.#pragma mark--------------NSThread 多线程方式(三)
    
    
    //方式一:(需要手动开启) //注:该方法有取消方法,但一般不用,因为不好控制
//    NSThread *thread1 = [[NSThread alloc] initWithTarget:self selector:@selector(calculate:) object:@"方式一"];
    //手动开启
//   [thread1 start];
   
    
    //方式二:
//    [NSThread detachNewThreadSelector:@selector(calculate:) toTarget:self withObject:@"方式二"];


5.  

#pragma mark--------------NSOperation和NSOperationQueue组合使用 多线程方式(四)
    
#pragma mark---------------NSOperation (只是一个操作,辅助程序,既可以在主线程中,也可以在子线程中)
    //方式一:NSInvocationOperation
//    要手动开启
    NSInvocationOperation *invocationOperation = [[NSInvocationOperation alloc] initWithTarget:self selector:@selector(printAQueue) object:nil];
    //[invocationOperation start];
    
    //方式二:NSBlockOperation:要手动开启
#warning 下面这句一定要写
    __weak typeof(self) temp = self;
    NSBlockOperation *block = [NSBlockOperation blockOperationWithBlock:^{
        [temp printBQueue];
    }];
    //[block start];
    
    
    //可以通过NSOperationQueue创建队列,向队列中添加操作,完成多任务同时执行,当最大并发数为1时,变成了串行
    NSOperationQueue *queue = [[NSOperationQueue alloc] init];
    
#warning 注意:一定要提前设置好并发数
    [queue setMaxConcurrentOperationCount:2];
    //将操作对象添加到队列中
    [queue addOperation:invocationOperation];
    [queue addOperation:block];
    

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值