GCD


一个线程就是一个任务的执行


/*
 

 
什么是进程:系统分配资源的最小单位(一个APP运行时在内存中所需要的所有资源)
 
什么是线程:cup运行的最小基本单位,一个线程就是一个任务
 
有什么区别: 1.一个进程可以包含多个线程,系统至少会为APP开辟一个进程,一个进程至少会有一个线程(主线程)
            2.
每个进程有自己独立的堆栈空间,一个进程奔溃(死掉)不会影响其他进程
            3.
线程没有自己独立的堆栈空间,统一使用进程的内存空间,一个线程死掉,整个进程都会死掉
 
多线程的实质:CPU快速的在各个线程之间切换,由于CPU的执行速度很快,我们根本感觉不到,就相当于多个任务同时执行,这也是为什么我们的电脑开得程序过多就会感觉性能下降的原因。

 */




#pragma mark 点击按钮执行的方法
- (IBAction)doButton:(id)sender {
   
//查看当前是否在主线程
//    NSLog(@"%d",[[NSThread currentThread] isMainThread]);
 
//线程阻塞(UI冻结)
   
/*
    //INTMAX_MAX
是支持的最大整形数字
    //
单一线程容易造成UI冻结
    for (NSInteger i =0; i < INTMAX_MAX; i++) {
        NSLog(@"
卡死了");
    }
    */

   
   
   
//1.开辟子线程的第一种方式*********************
   
/*
    //object:
通常使用object来完成从主线程向子线程传值的对象
    NSThread *thread = [[NSThread alloc] initWithTarget:self selector:@selector(doThread1:) object:@"123"];
    //
线程的优先级
    thread.threadPriority = 0.8;
    //
用这种方式创建的多线程需要手动开启
    [thread start];
   
    NSThread *thread2 = [[NSThread alloc] initWithTarget:self selector:@selector(doThread2:) object:nil];
    //
    thread2.threadPriority = 0.1;
    thread2.name = @"
窗口2";
    [thread2 start];
    */

   
//2.第二种方式开辟子线程的方式******************
   
//该方法不需要手动开启
    [
NSThread detachNewThreadSelector:@selector(doThread3:) toTarget:self withObject:nil];

   
//3.线程之间的互斥**************************
   
//线程互斥:因为线程没有自己独立的堆栈空间,都是使用进程的空间,所以有可能多个线程访问进程的同一块资源,这就会出现线程访问问题,多个线程访问同一个资源就叫做线程互斥,解决办法就是加线程锁
   
//加线程锁
   
   
NSLock *l =[[NSLock alloc] init];
   
   
NSThread *th1 = [[NSThread alloc] initWithTarget:self selector:@selector(doTh1:) object:l];
   
NSThread *th2 = [[NSThread alloc] initWithTarget:self selector:@selector(doTh1:) object:l];
    
NSThread *th3 = [[NSThread alloc] initWithTarget:self selector:@selector(doTh1:) object:l];
    [th1
start];
    [th2
start];
    [th3
start];
   
   
/*
    for (int i = 0; i < 100; i++) {
        NSLog(@"
主线程******");
    }
     */

   
}
/*
-(void)doThread1:(id)object
{
    //
因为在子线程中也需要做内存管理,而在MRC中用autorelease修饰的对象,需要自动释放池来释放对象,在子线程中,系统没有为我们创建自动释放池,需要我们自己手动创建一个自动释放池
    @autoreleasepool {
            //
该方法内部就是子线程
        NSLog(@"th1 =%d",[[NSThread currentThread] isMainThread]);
        NSLog(@"%@",object);
       
        for (int i = 0; i<100; i++) {
            NSLog(@"******
子线程");
        }
    }

}
 */

#pragma mark 第二个子线程执行的方法
/*
-(void)doThread2:(id)object
{
    @autoreleasepool {
        NSLog(@"%@",[[NSThread currentThread] name]);
        for (int i = 0; i < 100; i++) {
                NSLog(@"***
子线程二****");
        }
    }
}
 */

#pragma mark 第三个子线程执行的方法
-(void)doThread3:(id)object
{

       
NSURL *url = [NSURL URLWithString:BaseUrl];
       
NSURLRequest *request = [NSURLRequest requestWithURL:url];
       
NSData *data = [NSURLConnection sendSynchronousRequest:request returningResponse:nil error:nil];
       
UIImage *image = [UIImage imageWithData:data];
       
//不建议在Ui更新在子线程中写,因为子线程更新UI会存在潜在问题,并且耗时,费性能
       
//        self.imageView.image = image;
       
//从子线程回到主线程的方法(主要用于线程间的通信)
       
//waitUntilDone如果是YES就立刻跳转到主线程执行,执行完毕后再跳转回来接着执行下面的代码,如果NO,就行先把整个子线程的方法执行完毕后,再跳转到主线程执行
   
        [
self performSelectorOnMainThread:@selector(doMainThread:) withObject:image waitUntilDone:YES];
//            NSLog(@"11111111111111111111111111111111111111111111111");
   
/*
        for (int i = 0; i < 100; i++) {
            NSLog(@"******************************
线程三**");
        }
         */

   
}
#pragma mark -该方法是从子线程中回到主线程的方法
-(void)doMainThread:(id)object
{
   
self.imageView.image = object;
//    NSLog(@"000000000oooooooooooooooooooo=%d",[[NSThread currentThread] isMainThread]);
}

-(
void)doTh1:(id)object
{
   
NSLock *l = (NSLock *)object;

   
while (true) {
            [l
lock];
       
//假设有一百张票
       
static int num = 100;
        num--;
       
sleep(2);
       
NSLog(@"num=%d",num);
       
if (num==0) {
           
break;
        }
        [l
unlock];
    }
 
}


@end



//
//  UIImageView+CreateByUrl.m
//  Lesson22多线程下载
//
// 
// 
//

#import "UIImageView+CreateByUrl.h"

@implementation UIImageView (CreateByUrl)

-(
void)setImageByUrl:(NSString *)urlString
{
   
//block内部使用的变量
   
__block UIImageView *weakSelf = self;
   
//创建一个子线程队列来做数据请求
   
dispatch_queue_t downLoadQueue =dispatch_queue_create("downLoad", NULL);
   
//创建一个子线程
   
dispatch_async(downLoadQueue, ^{
       
NSURL *url = [NSURL URLWithString:urlString];
       
//同步
       
NSData *data = [NSData dataWithContentsOfURL:url];
       
//用请求回来的数据创建一个image
       
UIImage *image = [UIImage imageWithData:data];
       
//回到主线程
       
dispatch_sync(dispatch_get_main_queue(), ^{
          
//主线程更新UI
            weakSelf.
image = image;
        });
    });
}

@end




/  ViewController.m
//  Lesson22-多线程队列
//

//

#import "ViewController.h"

@interface ViewController ()

@end

@implementation ViewController

- (
void)viewDidLoad {
    [
super viewDidLoad];
   
// ***********NSObject******
   
     
//    [self performSelectorInBackground:@selector(doThread1:) withObject:@"123"];
//***********************2.NSOperationQueue********
   
//1.创建一个线程对列
   
NSOperationQueue *operation = [[NSOperationQueue alloc] init];
   
//2.在线程队列里面创建多线程
    [operation
addOperationWithBlock:^{
      
//block内部就是一个子线程
  
//        NSLog(@"block = %d",[[NSThread currentThread] isMainThread]);
       
//返回主线程
  
//        [self performSelectorOnMainThread:@selector(aaaa:) withObject:nil waitUntilDone:YES];
       
    }];
   
//*****3.NSOperationQueue
   
//1.创建队列
   
NSOperationQueue * op = [[NSOperationQueue alloc] init];
   
//创建子线程对象
   
NSInvocationOperation *inv = [[NSInvocationOperation alloc] initWithTarget:self selector:@selector(doOp1:) object:nil];
    inv.
queuePriority = NSOperationQueuePriorityVeryHigh;
   
//(优先级)效果不明显
   
NSInvocationOperation *inv2 = [[NSInvocationOperation alloc] initWithTarget:self selector:@selector(doOp2:) object:nil];
    inv2.
queuePriority = NSOperationQueuePriorityVeryLow;
   
//将子线程添加到线程队列
    [op
addOperation:inv];
    [op
addOperation:inv2];
   
//**************4.GCD(C语言)
   
/*
    //1.
创建一个队列
    //
参数一:线程队列的名字
    //
参数二:要创建线程队列的类型(串行,并行)
    dispatch_queue_t queue = dispatch_queue_create("GCD", NULL);
    //2.
在队列里面创建子线程
    //
参数一:子线程创在哪个队列里,参数二,block里面就是子线程
    dispatch_async(queue, ^{
        //
子线程
        NSLog(@"queue=%d",[[NSThread currentThread] isMainThread]);
        //
回到主线程的方法dispatch_get_main_queue()
        dispatch_sync(dispatch_get_main_queue(), ^{
            NSLog(@"sync=%d",[[NSThread currentThread] isMainThread]);
        });
    });
    */

//5.***5GCD线程队列的串行
   
/*
    //
默认是串行队列,串行队列的特点:队列里面的子线程是顺序执行的
    dispatch_queue_t serialQueue = dispatch_queue_create("serialQueue", DISPATCH_QUEUE_SERIAL);
    dispatch_async(serialQueue, ^{
        for (int i =0; i < 10; i++) {
            NSLog(@"11111");
        }
    });
    dispatch_async(serialQueue, ^{
        for (int i = 0; i < 10; i++) {
            NSLog(@"22222222");
        }
    });
    */

//6.*****GCD并行******
   
//DISPATCH_QUEUE_CONCURRENT表示并行队列 并行队列的特点:受队列管理的子线程是并发执行的
   
dispatch_queue_t concurrent = dispatch_queue_create("concurrent", DISPATCH_QUEUE_CONCURRENT);
   
dispatch_async(concurrent, ^{
       
for (int i = 0; i < 10; i++) {
           
NSLog(@"11111111111");
        }
    });
   
dispatch_async(concurrent, ^{
       
for (int i = 0; i < 10; i++) {
           
NSLog(@"2222");

        }

    });

   
}

/*
-(void)doThread1:(id)object
{
    NSLog(@"dothread=%d",[[NSThread currentThread] isMainThread]);
}
*/

-(
void)doOp1:(id)object
{
   
/*
    for (int i =0 ; i < 100; i++) {
        NSLog(@"op1 *******");
    }
   */

}
-(
void)doOp2:(id)object
{
   
/*
    for (int i =0 ; i < 100; i++) {
       NSLog(@" ==================op2");
    }
   
    */


}

转载于:https://my.oschina.net/JKzhong/blog/518981

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值