無標題文章duo xian

屏幕快照 2017-06-18 下午11.46.26.png

Pthread

//1.創(chuàng)建線程對象
    pthread_t thread;
    
    //2.創(chuàng)建線程
    /*
     第一個參數(shù):線程對象 傳遞地址
     第二個參數(shù):線程的屬性 NULL
     第三個參數(shù):指向函數(shù)的指針
     第四個參數(shù):函數(shù)需要接受的參數(shù)
     */
    pthread_create(&thread, NULL, task, NULL);

void *task(void *param)
{
    for (NSInteger i = 0; i<10000; i++) {
        NSLog(@"%zd----%@",i,[NSThread currentThread]);
    }
    
//    NSLog(@"%@--------",[NSThread currentThread]);
    return NULL;
}

NSThread

//1.創(chuàng)建線程
    /*
     第一個參數(shù):目標對象  self
     第二個參數(shù):方法選擇器 調用的方法
     第三個參數(shù):前面調用方法需要傳遞的參數(shù) nil
     */
    XMGThread *threadA = [[XMGThread alloc]initWithTarget:self selector:@selector(run:) object:@"ABC"];
    
    //設置屬性
    threadA.name = @"線程A";
    //設置優(yōu)先級  取值范圍 0.0 ~ 1.0 之間 最高是1.0 默認優(yōu)先級是0.5
    threadA.threadPriority = 1.0;
    
    //2.啟動線程
    [threadA start];

[NSThread detachNewThreadSelector:@selector(run:) toTarget:self withObject:@"分離子線程"];

3.開啟后臺線程
[self performSelectorInBackground:@selector(run:) withObject:@"開啟后臺線程"];
線程安全
    while (1) {
        
    //鎖:必須是全局唯一的
    //1.注意枷鎖的位置
    //2.注意枷鎖的前提條件,多線程共享同一塊資源
    //3.注意加鎖是需要代價的,需要耗費性能的
    //4.加鎖的結果:線程同步
        
    @synchronized(self) {
        //線程1
        //線程2
        //線程3
        NSInteger count = self.totalCount;
        if (count >0) {
            
            for (NSInteger i = 0; i<1000000; i++) {
            }
            
            self.totalCount = count - 1;
            //賣出去一張票
            NSLog(@"%@賣出去了一張票,還剩下%zd張票", [NSThread currentThread].name,self.totalCount);
        }else
        {
            NSLog(@"不要回公司上班了");
            break;
        }
        }
    }

GCD

屏幕快照 2017-06-19 上午12.11.12.png

1.異步函數(shù)+并發(fā)隊列:會開啟多條線程,隊列中的任務是并發(fā)執(zhí)行

    //獲得全局并發(fā)隊列
    /*
     第一個參數(shù):優(yōu)先級
     第二個參數(shù):
     */
    dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
    
    NSLog(@"---satrt----");
    
    //2.1>封裝任務2>添加任務到隊列中
    /*
     第一個參數(shù):隊列
     第二個參數(shù):要執(zhí)行的任務
     */
    dispatch_async(queue, ^{
        NSLog(@"download1----%@",[NSThread currentThread]);
    });

2.異步函數(shù)+串行隊列:會開線程,開一條線程,隊列中的任務是串行執(zhí)行的

//1.創(chuàng)建隊列
    dispatch_queue_t queue = dispatch_queue_create("download", DISPATCH_QUEUE_SERIAL);

    //2.封裝操作
    dispatch_async(queue, ^{
        NSLog(@"download1----%@",[NSThread currentThread]);
    });

3.同步函數(shù)+并發(fā)隊列:不會開線程,任務是串行執(zhí)行的

//1.創(chuàng)建隊列
    dispatch_queue_t queue = dispatch_queue_create("com.520it.download", DISPATCH_QUEUE_CONCURRENT);
    
    NSLog(@"---start---");
    //2.封裝任務
    dispatch_sync(queue, ^{
        NSLog(@"download1----%@",[NSThread currentThread]);
    });

4.同步函數(shù)+串行隊列:不會開線程,任務是串行執(zhí)行的

//1.創(chuàng)建隊列
    dispatch_queue_t queue = dispatch_queue_create("com.520it.download", DISPATCH_QUEUE_SERIAL);
    
    //2.封裝任務
    dispatch_sync(queue, ^{
        NSLog(@"download1----%@",[NSThread currentThread]);
    });

5.異步函數(shù)+主隊列:所有任務都在主線程中執(zhí)行,不會開線程

//1.獲得主隊列
    dispatch_queue_t queue = dispatch_get_main_queue();

    //2.異步函數(shù)
    dispatch_async(queue, ^{
        NSLog(@"download1----%@",[NSThread currentThread]);
    });

//同步函數(shù)+主隊列:死鎖
//注意:如果該方法在子線程中執(zhí)行,那么所有的任務在主線程中執(zhí)行,
-(void)syncMain
{
    //1.獲得主隊列
    dispatch_queue_t queue = dispatch_get_main_queue();
    
    NSLog(@"start----");
    //2.同步函數(shù)
    //同步函數(shù):立刻馬上執(zhí)行,如果我沒有執(zhí)行完畢,那么后面的也別想執(zhí)行
    //異步函數(shù):如果我沒有執(zhí)行完畢,那么后面的也可以執(zhí)行
    dispatch_sync(queue, ^{
        NSLog(@"download1----%@",[NSThread currentThread]);
    });
    
    dispatch_sync(queue, ^{
        NSLog(@"download2----%@",[NSThread currentThread]);
    });
    
    dispatch_sync(queue, ^{
        NSLog(@"download3----%@",[NSThread currentThread]);
    });
    
    NSLog(@"end---");
}

死鎖解釋

先請看下面這張圖,相信大家都知道會死鎖,為什么呢。
往串行隊列添加的任務需要等到串行隊列前面的任務都執(zhí)行完畢才會開始執(zhí)行。拋開你所謂的堵塞概念,我不認為這是適合的描述。對于在主線程,你可以認為每一語句都是將任務插入主隊列。調用dispatch_sync這個函數(shù)相當于將一個任務插入主隊列,這個函數(shù)的作用是將一個任務插入指定隊列,當這個函數(shù)里的Block執(zhí)行完畢以后,這個函數(shù)才會返回,即這個調用這個dispatch_sync的任務結束,主隊列繼續(xù)往下添加任務。我上面說了,串行的任務添加后需要等前面的任務都執(zhí)行完才會執(zhí)行的。所以Block里的任務需要等dispatch_sync這個調用執(zhí)行完才會執(zhí)行,然而dispatch_sync并不會返回。
第二個是創(chuàng)建了一個空的串行隊列,dispatch_sync這個是主隊列添加的任務,工作是將一個任務添加到這個新創(chuàng)建的隊列上,由于指定的隊列前面沒有其他任務,所以這個任務先執(zhí)行,然后返回,dispatch_sync返回,主隊列繼續(xù)往下添加任務。


線程通訊
//1.創(chuàng)建子線程下載圖片
    //DISPATCH_QUEUE_PRIORITY_DEFAULT 0
    dispatch_async(dispatch_get_global_queue(0, 0), ^{
       
        //1.1 確定url
        NSURL *url = [NSURL URLWithString:@"http://a.hiphotos.baidu.com/zhidao/wh%3D450%2C600/sign=da0ec79c738da9774e7a8e2f8561d42f/c83d70cf3bc79f3d6842e09fbaa1cd11738b29f9.jpg"];
        
        //1.2 下載二進制數(shù)據(jù)到本地
       NSData *imageData =  [NSData dataWithContentsOfURL:url];
        
        //1.3 轉換圖片
        UIImage *image = [UIImage imageWithData:imageData];
        
        NSLog(@"download----%@",[NSThread currentThread]);
        
        //更新UI
//        dispatch_async(dispatch_get_main_queue(), ^{
        dispatch_sync(dispatch_get_main_queue(), ^{
            self.imageView.image = image;
             NSLog(@"UI----%@",[NSThread currentThread]);
        });
        
    });

常用函數(shù)

/*
     第一個參數(shù):DISPATCH_TIME_NOW 從現(xiàn)在開始計算時間
     第二個參數(shù):延遲的時間 2.0 GCD時間單位:納秒
     第三個參數(shù):隊列
     */
    dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(2.0 * NSEC_PER_SEC)), queue, ^{
        NSLog(@"GCD----%@",[NSThread currentThread]);
    });

//一次性代碼
//不能放在懶加載中的,應用場景:單例模式
-(void)once
{
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        NSLog(@"---once----");
    });
}

柵欄函數(shù)

//0.獲得全局并發(fā)隊列
    //柵欄函數(shù)不能使用全局并發(fā)隊列
    //dispatch_queue_t queue =  dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
    dispatch_queue_t queue = dispatch_queue_create("download", DISPATCH_QUEUE_CONCURRENT);
    
    //1.異步函數(shù)
    dispatch_async(queue, ^{
       
        for (NSInteger i = 0; i<100; i++) {
            NSLog(@"download1-%zd-%@",i,[NSThread currentThread]);
        }
        
    });
    
    dispatch_async(queue, ^{
        
        for (NSInteger i = 0; i<100; i++) {
            NSLog(@"download2-%zd-%@",i,[NSThread currentThread]);
        }
    });
    
    
    //柵欄函數(shù)
    dispatch_barrier_async(queue, ^{
       
        NSLog(@"+++++++++++++++++++++++++++++");
    });
    
    dispatch_async(queue, ^{
        
        for (NSInteger i = 0; i<100; i++) {
            NSLog(@"download3-%zd-%@",i,[NSThread currentThread]);
        }
    });
    
    dispatch_async(queue, ^{
        
        for (NSInteger i = 0; i<100; i++) {
            NSLog(@"download4-%zd-%@",i,[NSThread currentThread]);
        }
    });

download4 download3 會在 download1 download2后執(zhí)行

快速迭代

//開子線程和主線程一起完成遍歷任務,任務的執(zhí)行時并發(fā)的

-(void)applyDemo
{
    /*
     第一個參數(shù):遍歷的次數(shù)
     第二個參數(shù):隊列(并發(fā)隊列)
     第三個參數(shù):index 索引
     */
    dispatch_apply(10, dispatch_get_global_queue(0, 0), ^(size_t index) {
        NSLog(@"%zd---%@",index,[NSThread currentThread]);
    });
}

GCD另一種寫法

/*
     第一個參數(shù):隊列
     第二個參數(shù):參數(shù)
     第三個參數(shù):要調用的函數(shù)的名稱
     */
    dispatch_async_f(dispatch_get_global_queue(0, 0), NULL, task);
    dispatch_async_f(dispatch_get_global_queue(0, 0), NULL, task);
    dispatch_async_f(dispatch_get_global_queue(0, 0), NULL, task);

隊列組

第一種
//1.創(chuàng)建隊列
    dispatch_queue_t queue =dispatch_get_global_queue(0, 0);
    
    //2.創(chuàng)建隊列組
    dispatch_group_t group = dispatch_group_create();
    
    //3.異步函數(shù)
    /*
     1)封裝任務
     2)把任務添加到隊列中
     dispatch_async(queue, ^{
     NSLog(@"1----%@",[NSThread currentThread]);
     });
     */
    /*
     1)封裝任務
     2)把任務添加到隊列中
     3)會監(jiān)聽任務的執(zhí)行情況,通知group
     */
    dispatch_group_async(group, queue, ^{
        NSLog(@"1----%@",[NSThread currentThread]);
    });
    
    
    dispatch_group_async(group, queue, ^{
        NSLog(@"2----%@",[NSThread currentThread]);
    });
    
    dispatch_group_async(group, queue, ^{
        NSLog(@"3----%@",[NSThread currentThread]);
    });
    
    //攔截通知,當隊列組中所有的任務都執(zhí)行完畢的時候回進入到下面的方法
    dispatch_group_notify(group, queue, ^{
        
        NSLog(@"-------dispatch_group_notify-------");
    });
    
    //    NSLog(@"----end----");

第二種

//1.創(chuàng)建隊列
    dispatch_queue_t queue =dispatch_get_global_queue(0, 0);
    
    //2.創(chuàng)建隊列組
    dispatch_group_t group = dispatch_group_create();
    
    //3.在該方法后面的異步任務會被納入到隊列組的監(jiān)聽范圍,進入群組
    //dispatch_group_enter|dispatch_group_leave 必須要配對使用
    dispatch_group_enter(group);
    
    dispatch_async(queue, ^{
        NSLog(@"1----%@",[NSThread currentThread]);
        
        //離開群組
        dispatch_group_leave(group);
    });
    
    dispatch_group_enter(group);
    
    dispatch_async(queue, ^{
        NSLog(@"2----%@",[NSThread currentThread]);
    
        //離開群組
        dispatch_group_leave(group);
    });
    
    
    //攔截通知
    //問題?該方法是阻塞的嗎?  內部本身是異步的
//    dispatch_group_notify(group, queue, ^{
//        NSLog(@"-------dispatch_group_notify-------");
//    });
    
    //等待.死等. 直到隊列組中所有的任務都執(zhí)行完畢之后才能執(zhí)行
    //阻塞的
    dispatch_group_wait(group, DISPATCH_TIME_FOREVER);
    NSLog(@"----end----");

單利實現(xiàn)

ARC下

/0.提供全局變量
static XMGTool *_instance;

//1.alloc-->allocWithZone
+(instancetype)allocWithZone:(struct _NSZone *)zone
{
    //加互斥鎖解決多線程訪問安全問題
//    @synchronized(self) {
//        if (_instance == nil) {
//            _instance = [super allocWithZone:zone];
//        }
//    }
    
    //本身就是線程安全的
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        _instance = [super allocWithZone:zone];
    });
    
    return _instance;
}

//2.提供類方法
+(instancetype)shareTool
{
    return [[self alloc]init];
}

//3.嚴謹
-(id)copyWithZone:(NSZone *)zone
{
    return _instance;
}

-(id)mutableCopyWithZone:(NSZone *)zone
{
    return _instance;
}

MRC下:

#if __has_feature(objc_arc)
//條件滿足 ARC
#else
// MRC
-(oneway void)release
{
    
}

-(instancetype)retain
{
    return _instance;
}

//習慣
-(NSUInteger)retainCount
{
    return MAXFLOAT;
}

#endif

NSOperation

基本使用

//1.創(chuàng)建操作,封裝任務
    /*
     第一個參數(shù):目標對象 self
     第二個參數(shù):調用方法的名稱
     第三個參數(shù):前面方法需要接受的參數(shù) nil
     */
     NSInvocationOperation *op1 = [[NSInvocationOperation alloc]initWithTarget:self selector:@selector(download1) object:nil];
     NSInvocationOperation *op2 = [[NSInvocationOperation alloc]initWithTarget:self selector:@selector(download2) object:nil];
     NSInvocationOperation *op3 = [[NSInvocationOperation alloc]initWithTarget:self selector:@selector(download3) object:nil];
    
    //2.啟動|執(zhí)行操作
     [op1 start];
     [op2 start];
     [op3 start];

上面的使用運行在主線程

//1.創(chuàng)建操作
    NSBlockOperation *op1 = [NSBlockOperation blockOperationWithBlock:^{
        NSLog(@"1----%@",[NSThread currentThread]);
    }];
    
    NSBlockOperation *op2 = [NSBlockOperation blockOperationWithBlock:^{
        NSLog(@"2----%@",[NSThread currentThread]);
    }];
    
    NSBlockOperation *op3 = [NSBlockOperation blockOperationWithBlock:^{
        NSLog(@"3----%@",[NSThread currentThread]);
    }];
    
    //追加任務
    //注意:如果一個操作中的任務數(shù)量大于1,那么會開子線程并發(fā)執(zhí)行任務(就是此列加block任務開線程,不加跟上面一樣)
    //注意:不一定是子線程,有可能是主線程
    [op3 addExecutionBlock:^{
        NSLog(@"4---%@",[NSThread currentThread]);
    }];
    
    [op3 addExecutionBlock:^{
        NSLog(@"5---%@",[NSThread currentThread]);
    }];
    
    [op3 addExecutionBlock:^{
        NSLog(@"6---%@",[NSThread currentThread]);
    }];
    
    //2.啟動
    [op1 start];
    [op2 start];
    [op3 start];

NSOperationQueue


    //1.創(chuàng)建操作,封裝任務
    /*
     第一個參數(shù):目標對象 self
     第二個參數(shù):調用方法的名稱
     第三個參數(shù):前面方法需要接受的參數(shù) nil
     */
    NSInvocationOperation *op1 = [[NSInvocationOperation alloc]initWithTarget:self selector:@selector(download1) object:nil];
    NSInvocationOperation *op2 = [[NSInvocationOperation alloc]initWithTarget:self selector:@selector(download2) object:nil];
    NSInvocationOperation *op3 = [[NSInvocationOperation alloc]initWithTarget:self selector:@selector(download3) object:nil];
    
    //2.創(chuàng)建隊列
    /*
     GCD:
     串行類型:create & 主隊列
     并發(fā)類型:create & 全局并發(fā)隊列
     NSOperation:
     主隊列:   [NSOperationQueue mainQueue] 和GCD中的主隊列一樣,串行隊列
     非主隊列: [[NSOperationQueue alloc]init]  非常特殊(同時具備并發(fā)和串行的功能)
     //默認情況下,非主隊列是并發(fā)隊列
     */
    NSOperationQueue *queue = [[NSOperationQueue alloc]init];
    
    //3.添加操作到隊列中
    [queue addOperation:op1];   //內部已經調用了[op1 start]
    [queue addOperation:op2];
    [queue addOperation:op3];

block的那種用法一樣
最后編輯于
?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
【社區(qū)內容提示】社區(qū)部分內容疑似由AI輔助生成,瀏覽時請結合常識與多方信息審慎甄別。
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發(fā)布,文章內容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

相關閱讀更多精彩內容

  • 從哪說起呢? 單純講多線程編程真的不知道從哪下嘴。。 不如我直接引用一個最簡單的問題,以這個作為切入點好了 在ma...
    Mr_Baymax閱讀 2,911評論 1 17
  • GCD筆記 總結一下多線程部分,最強大的無疑是GCD,那么先從這一塊部分講起. Dispatch Queue的種類...
    jins_1990閱讀 836評論 0 1
  • 背景 擔心了兩周的我終于輪到去醫(yī)院做胃鏡檢查了!去的時候我都想好了最壞的可能(胃癌),之前在網上查的癥狀都很相似。...
    Dely閱讀 9,401評論 21 42
  • 目錄(GCD): 關鍵詞 混淆點 場景應用 總結 1. 關鍵詞 線程概念: 獨立執(zhí)行的代碼段,一個線程同時間只能執(zhí)...
    Ryan___閱讀 1,370評論 0 3
  • 3.GCD GCD的全稱是Grand Central Dispatch,提供了非常多的純C語言的函數(shù) GCD的優(yōu)勢...
    Mario_ZJ閱讀 602評論 0 0

友情鏈接更多精彩內容