iOS 多线程 NSThread NSOperation NSOperationQueue GCD 线程锁 线程阻塞

iPhone中的线程应用并不是无节制的,官方给出的资料显示,iPhone OS下的主线程的堆栈大小是1M,第二个线程开始就是512KB,并且该值不能通过编译器开关或线程API函数来更改,只有主线程有直接修改UI的能力,所以一些数据层面可以开辟线程来操作进行,iOS线程的操作方法有NSThread NSOperation NSOperationQueue GCD:

NSThread方法有

//NSThread自动
- (IBAction)didClickNSThreadAutoButtonAction:(id)sender {
    
    //创建一个子线程,即子线程
    //selector在子线程中运行方法,target在子线程执行方法对象,object是方法参数
    [NSThread detachNewThreadSelector:@selector(cycle) toTarget:self withObject:nil];
    
    
}
//NSthread手动
- (IBAction)didClickNSThreadHandButtonAction:(id)sender {
    
    
    NSThread *thread = [[NSThread alloc]initWithTarget:self selector:@selector(cycle) object:nil];
    
    [thread start];//手动开启线程
    
    
}

通过NSObject的类目方法,直接创建线程

//NSOperation invocation方法创建线程
- (IBAction)didClickInvocationButtonAction:(id)sender {
    
    //操作对象,封装方法实现和数据
    NSInvocationOperation *operation = [[NSInvocationOperation alloc]initWithTarget:self selector:@selector(cycle) object:nil];
    
    [operation start];//开始执行operation中存储的方法
    
}

使用NSOperation方法

//NSOperation invocation方法创建线程
- (IBAction)didClickInvocationButtonAction:(id)sender {
    
    //操作对象,封装方法实现和数据
    NSInvocationOperation *operation = [[NSInvocationOperation alloc]initWithTarget:self selector:@selector(cycle) object:nil];
    
    [operation start];//开始执行operation中存储的方法
    
}

//NSOperation block方法
- (IBAction)didClickBlockButtonAction:(id)sender {
    
    NSBlockOperation *operation = [NSBlockOperation blockOperationWithBlock:^{
        
        //封装要执行的方法
        for (int i = 0 ; i < 10; i++) {
            
            NSLog(@"当前线程 == %@ 是否是主线程 == %d  i : %d",[NSThread currentThread],[NSThread isMainThread],i);
        }

        
    }];
    
    //执行方法
    [operation start];
    
}

使用NSOperationQueue 线程列队

//NSOperationQueue 创建线程队列
- (IBAction)didClickOperationQueueButtonAction:(id)sender {
    
    //线程区分:脱离线程和非脱离线程
    //脱离线程:线程中的功能实现完成后,线程会会被关闭销毁.NSThread NSObject类目方法创建的线程.默认是脱离线程
    //非脱离线程:线程中的功能实现后,线程进入睡眠状态,等待再次使用. 脱离线程中的runloop运行且不在关闭,则变成非脱离线程. NSOperationQueue创建的线程是非脱离线程.
    
    //操作队列实现多个线程并发执行.
    //线程同步:当前一个线程执行完成后,下一个线程在执行开始.
    //如何实现线程同步:将操作队列的最大并发数设置成1;
    
    //创建线程队列
    NSOperationQueue *queue = [[NSOperationQueue alloc]init];
    
    //设置操作队列同时最大线程并发个数
    queue.maxConcurrentOperationCount = 5;
    
    
    for (int i = 0; i < 10; i++) {
        
        NSInvocationOperation *operation = [[NSInvocationOperation alloc]initWithTarget:self selector:@selector(cycle) object:nil];
        //添加到线程队列中
        [queue addOperation:operation];
        
        [operation release];
    }
    
    
}

使用GCD方法出行队列

//GCD串行队列
- (IBAction)didClickSerialButtonAction:(id)sender {
    
    //串行队列有两种
    //mainQueue主队列,GCD创建并提供,在主队列中默认是串行队列,并且按照代码顺序执行
    dispatch_queue_t mainQueue = dispatch_get_main_queue();
    
    //向主队列添加任务,参数一 :管理任务的队列 参数二:封装任务代码的block
   
    dispatch_async(mainQueue, ^{
        
        NSLog(@"第一个任务===%@ 所在线程===%d",[NSThread currentThread],[NSThread isMainThread]);
        
    });
    dispatch_async(mainQueue, ^{
        
        NSLog(@"第二个任务===%@ 所在线程===%d",[NSThread currentThread],[NSThread isMainThread]);
        
    });
    
  
    dispatch_async(mainQueue, ^{
        
        NSLog(@"第三个任务===%@ 所在线程===%d",[NSThread currentThread],[NSThread isMainThread]);
        
    });
    dispatch_async(mainQueue, ^{
        
        NSLog(@"第四个任务===%@ 所在线程===%d",[NSThread currentThread],[NSThread isMainThread]);
        
    });
    dispatch_async(mainQueue, ^{
        
        NSLog(@"第五个任务===%@ 所在线程===%d",[NSThread currentThread],[NSThread isMainThread]);
        
    });
    
    //在定义队列,需要自己创建,并设置为串行 DISPATCH_QUEUE_SERIAL串行接口
//    dispatch_queue_t queue = dispatch_queue_create("myQueue", DISPATCH_QUEUE_SERIAL);
//    
//    dispatch_async(queue, ^{
//        NSLog(@"第一个任务===%@ 所在线程===%d",[NSThread currentThread],[NSThread isMainThread]);
//    });
//    dispatch_async(queue, ^{
//        NSLog(@"第二个任务===%@ 所在线程===%d",[NSThread currentThread],[NSThread isMainThread]);
//    });
//    dispatch_async(queue, ^{
//        NSLog(@"第三个任务===%@ 所在线程===%d",[NSThread currentThread],[NSThread isMainThread]);
//    });
//    dispatch_async(queue, ^{
//        NSLog(@"第四个任务===%@ 所在线程===%d",[NSThread currentThread],[NSThread isMainThread]);
//    });
//    dispatch_async(queue, ^{
//        NSLog(@"第五个任务===%@ 所在线程===%d",[NSThread currentThread],[NSThread isMainThread]);
//    });
    
}

使用GCD并行队列

//GCD并行队列
- (IBAction)didClickConcurrentButtonAction:(id)sender {
    
    //并行队列有两种
    
    //全局队列,CGD创建
//    dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
//    
//    dispatch_async(queue, ^{
//        NSLog(@"第一个任务===%@ 所在线程===%d",[NSThread currentThread],[NSThread isMainThread]);
//    });
//    dispatch_async(queue, ^{
//        NSLog(@"第二个任务===%@ 所在线程===%d",[NSThread currentThread],[NSThread isMainThread]);
//    });
//    dispatch_async(queue, ^{
//        NSLog(@"第三个任务===%@ 所在线程===%d",[NSThread currentThread],[NSThread isMainThread]);
//    });
//    dispatch_async(queue, ^{
//        NSLog(@"第四个任务===%@ 所在线程===%d",[NSThread currentThread],[NSThread isMainThread]);
//    });
//    dispatch_async(queue, ^{
//        NSLog(@"第五个任务===%@ 所在线程===%d",[NSThread currentThread],[NSThread isMainThread]);
//    });

    //自定义队列,需要自己创建,并设置并行队列 DISPATCH_QUEUE_CONCURRENT并行接口
  
    dispatch_queue_t queue = dispatch_queue_create("concurrent queue", DISPATCH_QUEUE_CONCURRENT);
    //添加任务
    dispatch_async(queue, ^{
        NSLog(@"第一个任务===%@ 所在线程===%d",[NSThread currentThread],[NSThread isMainThread]);
    });
    dispatch_async(queue, ^{
        NSLog(@"第二个任务===%@ 所在线程===%d",[NSThread currentThread],[NSThread isMainThread]);
    });
    dispatch_async(queue, ^{
        NSLog(@"第三个任务===%@ 所在线程===%d",[NSThread currentThread],[NSThread isMainThread]);
    });
    dispatch_async(queue, ^{
        NSLog(@"第四个任务===%@ 所在线程===%d",[NSThread currentThread],[NSThread isMainThread]);
    });
    dispatch_async(queue, ^{
        NSLog(@"第五个任务===%@ 所在线程===%d",[NSThread currentThread],[NSThread isMainThread]);
    });
    
    
}

使用GCD下载图片实际操作

//实际下载图片操作
- (IBAction)didClickGCDownloadButtonAction:(id)sender {
    
    dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
    
    //将任务添加到全局队列中,可以被派发到子线程中执行
    
    dispatch_async(queue, ^{
        
        //这是子线程中
        
        NSString *imageUrl = @"http://a.hiphotos.baidu.com/image/pic/item/96dda144ad3459824a56a41a0ef431adcaef845e.jpg";
        
        NSData *data = [NSData dataWithContentsOfURL:[NSURL URLWithString:imageUrl]];
        
        UIImage *image = [UIImage imageWithData:data];
        
        NSLog(@"image = %@",image);
        
        NSLog(@"任务===%@ 所在线程===%d",[NSThread currentThread],[NSThread isMainThread]);
        
        //在主线程显示图像
        //把任务添加到主队列中,主队列将任务派发到主线程中
        
        dispatch_async(dispatch_get_main_queue(), ^{
            
            //现在是主线程
            
            NSLog(@"任务===%@ 所在线程===%d",[NSThread currentThread],[NSThread isMainThread]);
            _imageView.image = image;
            
        });
        
    });
    
}

线程阻塞方法第一种:

[NSThread sleepForInterval:2.0]//意识是该线程等待2秒在运行

第二种设置线程阻塞
NSDate *date=[NSDate dateWithTimeIntervalSinceNow:4.0];
[NSThead sleepUntilDate:date];
 
线程锁经典案例卖火车票
 _lock = [[NSLock alloc]init];//创建互斥锁,多个线程共享使用
//卖火车票
- (void)saleTickets:(dispatch_queue_t)queue
{
    while (_surplusCount > 0) {
        [_lock lock];//获取互斥锁
        
        //每次执行休眠0.1秒
        [NSThread sleepForTimeInterval:0.1];
        
        const char *queueLabel = dispatch_queue_get_label(queue);
        
        NSString *label = [NSString stringWithUTF8String:queueLabel];
        
        NSLog(@"当前火车票由  %@   售出  余票: %d 张",label,_surplusCount);
        _surplusCount--;
        
        [_lock unlock];//解锁
        
    }
    
}

.........

郑重声明:本站内容如果来自互联网及其他传播媒体,其版权均属原媒体及文章作者所有。转载目的在于传递更多信息及用于网络分享,并不代表本站赞同其观点和对其真实性负责,也不构成任何其他建议。