iOS開發(fā)之多線程

進(jìn)程

1.進(jìn)程是指在系統(tǒng)中正在運(yùn)行的一個(gè)應(yīng)用程序
2.每個(gè)進(jìn)程之間是相互獨(dú)立的蒜撮,每個(gè)進(jìn)程均運(yùn)行在其專用且受保護(hù)的內(nèi)存空間中

線程

1.一個(gè)進(jìn)程要想執(zhí)行任務(wù),必須得有線程(每一個(gè)進(jìn)程至少要有一條線程)
2.一個(gè)進(jìn)程(程序)的所有任務(wù)都在線程中執(zhí)行

線程的串行

1.一個(gè)線程中任務(wù)的執(zhí)行是串行的
2.如果要在一個(gè)線程中執(zhí)行多個(gè)任務(wù),那么只能一個(gè)一個(gè)地按順序執(zhí)行這些任務(wù)
3.也就是說(shuō)萄焦,在同一時(shí)間內(nèi)驾诈,一個(gè)線程只能執(zhí)行一個(gè)任務(wù)
4.因此,也可以認(rèn)為線程是進(jìn)程中的一條執(zhí)行路徑

進(jìn)程和線程的比較

1.線程是CPU調(diào)用(執(zhí)行任務(wù))的最小單位
2.進(jìn)程是CPU分配資源和調(diào)度的單位
3.一個(gè)程序可以對(duì)應(yīng)多個(gè)進(jìn)程哑蔫,一個(gè)進(jìn)程中可以有多個(gè)線程钉寝,但至少要有一個(gè)線程
4.同一個(gè)進(jìn)程內(nèi)的線程共享進(jìn)程的資源

多線程

1.一個(gè)進(jìn)程中可以開啟多條線程弧呐,每個(gè)線程可以并發(fā)(同時(shí))執(zhí)行不同的任務(wù)
2.多線程可以提高任務(wù)的執(zhí)行效率

多線程的原理

1.同一時(shí)間,CPU只能處理一條線程嵌纲,只有一條線程在執(zhí)行(單核)
2.多線程并發(fā)(同時(shí))執(zhí)行俘枫,其實(shí)是CPU快速的在多條線程之間調(diào)度(切換)
3.如果CPU調(diào)度線程的時(shí)間足夠快,就造成了多線程并發(fā)執(zhí)行的假象
4.如果線程非常多逮走,會(huì)導(dǎo)致CPU在很多的線程之間調(diào)度鸠蚪,消耗大量的CPU資源,每條線程被調(diào)度執(zhí)行的頻次會(huì)降低(線程的執(zhí)行效率降低)

多線程的優(yōu)缺點(diǎn)

  • 優(yōu)點(diǎn):
    1.能適當(dāng)提高程序的執(zhí)行效率
    2.能適當(dāng)提高資源利用率(CPU师溅,內(nèi)存利用率)
  • 缺點(diǎn):
    1.創(chuàng)建線程是有開銷的茅信,iOS下主要成本包括:內(nèi)核數(shù)據(jù)結(jié)構(gòu)(大約1kb),椖钩簦空間(子線程512kb蘸鲸,主線程1mb,也可以使用-setStackSize:設(shè)置起便,但必須是4k的倍數(shù)棚贾,而且最小是16k),創(chuàng)建線程大約需要90毫秒的創(chuàng)建時(shí)間
    2.如果開啟大量的線程榆综,會(huì)降低程序的性能
    3.線程越多妙痹,CPU在調(diào)度線程上的開銷就越大
    4.程序設(shè)計(jì)更加復(fù)雜,比如線程之間的通信鼻疮,多線程的數(shù)據(jù)共享

多線程在iOS開發(fā)中的應(yīng)用

  • 主線程:
    一個(gè)iOS程序運(yùn)行后怯伊,默認(rèn)會(huì)開啟一條線程,稱為主線程或UI線程

  • 主線程的主要作用:
    1.顯示/刷新UI界面
    2.處理UI事件(比如點(diǎn)擊事件判沟,滾動(dòng)事件耿芹,拖拽事件等)

  • 主線程的使用注意:
    1.不要將比較耗時(shí)的操作放到主線程中
    2.耗時(shí)操作會(huì)卡住主線程,嚴(yán)重影響UI的流暢度挪哄,給用戶一種卡的壞體驗(yàn)

  • 耗時(shí)操作的執(zhí)行
    將耗時(shí)操作放在子線程(后臺(tái)線程吧秕,非主線程)

  • 獲得主線程

    NSThread *main=[NSThread mainThread];

  • 獲得當(dāng)前線程

    NSThread *current=[NSThread currentThread];

  • 判斷是否是主線程
    1.number==1?
    2.類方法
    BOOL isMain= [NSThread isMainThread];
    3.對(duì)象方法
    BOOL ifMain=[current isMainThread];

  • iOS中多線程的實(shí)現(xiàn)方案
技術(shù)方案 簡(jiǎn)介 語(yǔ)言 線程生命周期 使用頻率
pthread 一套通用的多線程API;
適用于unix/linux/windows等系統(tǒng)迹炼;
跨平臺(tái)/可移植砸彬;
使用難度大
C 程序員管理 幾乎不用
NSThread 使用更加面向?qū)ο螅?br>簡(jiǎn)單易用,可直接操作線程對(duì)象 OC 程序員管理 偶爾使用
GCD 旨在替代NSThread 等線程技術(shù)斯入;
充分利用設(shè)備的多核
C 自動(dòng)管理 經(jīng)常使用
NSOperation 基于GCD(底層是GCD)砂碉;
比GCD 多了一些更簡(jiǎn)單實(shí)用的功能;
使用更加面向?qū)ο?/td>
OC 自動(dòng)管理 經(jīng)常使用

pthread的簡(jiǎn)單使用

1.#import <pthread.h>
2. //創(chuàng)建線程對(duì)象
    pthread_t thread;
    //創(chuàng)建線程
    /*
     第一個(gè)參數(shù):線程對(duì)象 傳遞地址
     第二個(gè)參數(shù):線程的屬性 可設(shè)為null
     第三個(gè)參數(shù):指向函數(shù)的指針
     第四個(gè)參數(shù):函數(shù)需要接受的參數(shù)
     */
    pthread_create(&thread, NULL, test, NULL);

void *test(void * param){ 
    return NULL;
}

NSThread的基本使用

  • 方法一
    /*
     第一個(gè)參數(shù):目標(biāo)對(duì)象
     第二個(gè)參數(shù):方法選擇器 調(diào)用的方法
     第三個(gè)參數(shù):前面調(diào)用方法需要傳遞的參數(shù) 可以為nil
     */
    NSThread *subthread=[[NSThread alloc]initWithTarget:self selector:@selector(run:) object:@"123"];
    //設(shè)置線程的名字
    subthread.name=@"subthread";
    //優(yōu)先級(jí)  0.0(最低)--0.5(默認(rèn))--1.0( 最高)
    subthread.threadPriority=1;
    //需要手動(dòng)啟動(dòng)線程
    [subthread start];

-(void)run:(NSString *)param{
    
}
  • 方法二
//分離子線程刻两,自動(dòng)啟動(dòng)線程
[NSThread detachNewThreadSelector:@selector(run:) toTarget:self withObject:@"分離子線程"];
  • 方法三
//開啟一條后臺(tái)線程
[self performSelectorInBackground:@selector(run:) withObject:@"開啟一條后臺(tái)線程"];
  • 后兩種方法的優(yōu)缺點(diǎn)
    1.優(yōu)點(diǎn):
    簡(jiǎn)單快捷
    2.缺點(diǎn):
    沒(méi)有辦法拿到線程對(duì)象增蹭,無(wú)法設(shè)置優(yōu)先級(jí)或其他屬性

  • NSThread的生命周期
    當(dāng)線程中的任務(wù)執(zhí)行完畢后才被釋放

  • 控制線程的狀態(tài)
    1.創(chuàng)建線程
    init
    新建, 此時(shí)在內(nèi)存中存在磅摹,但是不在可調(diào)度線程池中
    2.啟動(dòng)線程
    -(void)start滋迈;
    進(jìn)入就緒狀態(tài)霎奢,進(jìn)入可調(diào)度線程池,當(dāng)CPU調(diào)度時(shí)饼灿,進(jìn)入運(yùn)行狀態(tài)椰憋,當(dāng)線程任務(wù)執(zhí)行完畢,自動(dòng)進(jìn)入死亡狀態(tài)
    3.阻塞/暫停線程
    +(void)sleepUntilDate:(NSDate *)date;
    +(void)sleepForTimeInterval:(NSTimeInterval)ti;
    進(jìn)入阻塞狀態(tài)赔退,推出可調(diào)度線程池,當(dāng)時(shí)間到時(shí)证舟,再次進(jìn)入就緒狀態(tài)硕旗,進(jìn)入可調(diào)度池
    4.強(qiáng)制停止線程
    +(void)exit;
    進(jìn)入死亡狀態(tài)女责,一旦線程死亡了漆枚,就不能再次開啟任務(wù)

  • 線程安全
    多線程的安全隱患
    1.資源共享
    一塊資源可能會(huì)被多個(gè)線程共享,也就是多個(gè)線程可能會(huì)訪問(wèn)同一塊資源
    比如多個(gè)線程訪問(wèn)同一個(gè)對(duì)象抵知,同一個(gè)變量墙基,同一個(gè)文件
    當(dāng)多個(gè)線程訪問(wèn)同一塊資源時(shí),很容易引發(fā)數(shù)據(jù)錯(cuò)亂和數(shù)據(jù)安全問(wèn)題

  • 安全隱患解決--互斥鎖
    互斥鎖使用格式

@synchronized(鎖對(duì)象刷喜,通常為self){
//需要鎖定的代碼
}

鎖:必須是全局唯一的一把鎖残制,
鎖定一份代碼只用一把鎖,用多把鎖是無(wú)效的
1.注意加鎖的位置
2.注意加鎖的前提條件,多線程共享同一塊資源
3.注意加鎖是需要付出代價(jià)的掖疮,需要耗費(fèi)性能
4.加鎖的結(jié)果:線程同步
線程同步:多條線程在同一條線上執(zhí)行(按順序的執(zhí)行任務(wù))

  • 互斥鎖的優(yōu)缺點(diǎn)
    優(yōu)點(diǎn):
    能有效防止因多線程搶奪資源造成的數(shù)據(jù)安全問(wèn)題
    缺點(diǎn):
    需要消耗大量的CPU資源

  • 互斥鎖的使用前提:
    多條線程搶奪同一塊資源

  • 原子和非原子屬性
    oc在定義屬性時(shí)有nonatomic和atomic兩種選擇
    atomic:原子屬性初茶,為setter方法加鎖(默認(rèn)就是atomic)
    線程安全,但需要消耗大量的資源
    nonatomic:非原子屬性浊闪,不會(huì)為setter方法加鎖
    非線性安全恼布,適合內(nèi)存小的移動(dòng)設(shè)備

  • iOS開發(fā)的建議
    1.所有屬性都聲明為nonatomic
    2.盡量避免多線程搶奪同一資源
    3.盡量將加鎖,資源搶奪的業(yè)務(wù)邏輯交給服務(wù)器端處理搁宾,減小移動(dòng)客戶端的壓力

  • 線程間通信
    在一個(gè)進(jìn)程中折汞,線程往往不是孤立存在的,多個(gè)線程之間需要經(jīng)常進(jìn)行通信

  • 線程間通信的體現(xiàn)
    1.一個(gè)線程傳遞數(shù)據(jù)給另外一個(gè)線程
    2.在一個(gè)線程中執(zhí)行完特定任務(wù)后盖腿,轉(zhuǎn)到另一個(gè)線程繼續(xù)執(zhí)行任務(wù)
    線程間通信常用方法

-(void)performSelectorOnMainThread:(SEL)aSelector withObject:(id)arg waitUntilDone:(BOOL)wait;
-(void)performSelector:(SEL)aSelector onThread:(NSThread *)thr withObject:(id)arg waitUntilDone:(BOOL)wait;

GCD

純c語(yǔ)言爽待,提供了非常多強(qiáng)大的函數(shù)

  • gcd的優(yōu)勢(shì)
    1.gcd是蘋果公司為多核的并行運(yùn)算提出的解決方案
    2.gcd會(huì)自動(dòng)利用更多的cpu內(nèi)核(比如雙核,四核)
    3.gcd會(huì)自動(dòng)管理線程的生命周期(創(chuàng)建線程奸忽,調(diào)度任務(wù)堕伪,銷毀線程)
    4.程序員只需要告訴gcd想要執(zhí)行什么任務(wù),不需要編寫任何線程管理代碼

  • 任務(wù)和隊(duì)列
    任務(wù):執(zhí)行什么操作
    隊(duì)列:用來(lái)存放任務(wù)

  • gcd的使用就兩個(gè)步驟
    1.定制任務(wù)栗菜,確定想做的事情
    2.將任務(wù)添加到隊(duì)列中欠雌,gcd會(huì)自動(dòng)將隊(duì)列中的任務(wù)取出,放到對(duì)應(yīng)的線程中執(zhí)行

  • 任務(wù)的取出遵循隊(duì)列的FIFO原則:先進(jìn)先出

  • 執(zhí)行任務(wù)
    同步:只能在當(dāng)前線程中執(zhí)行任務(wù)疙筹,不具備開啟新線程的能力富俄,需要立刻執(zhí)行禁炒,執(zhí)行完畢再執(zhí)行下面的
    dispatch_sync(dispatch_queue_t queue, ^(void)block);
    異步:可以在新的線程中執(zhí)行任務(wù),具備開啟新線程的能力霍比,即使沒(méi)有執(zhí)行完畢幕袱,后面的也可以執(zhí)行
    dispatch_async(dispatch_queue_t _Nonnull queue, ^(void)block);

  • 隊(duì)列
    并發(fā)隊(duì)列:可以讓多個(gè)任務(wù)并發(fā)(同時(shí))執(zhí)行(自動(dòng)開啟多個(gè)線程同時(shí)執(zhí)行任務(wù))
    并發(fā)功能只有在異步函數(shù)下才有效
    串行隊(duì)列:讓任務(wù)一個(gè)接著一個(gè)地執(zhí)行(一個(gè)任務(wù)執(zhí)行完畢后,在執(zhí)行下一個(gè)任務(wù))

  • 同步和異步主要影響:能不能開啟新的線程

  • 并發(fā)和串行主要影響:任務(wù)的執(zhí)行方式

  • gcd的基本使用

//1.創(chuàng)建隊(duì)列
    /*
     第一個(gè)參數(shù):c語(yǔ)言的字符串悠瞬,就是一個(gè)標(biāo)識(shí)符们豌,用來(lái)區(qū)分隊(duì)列,沒(méi)有實(shí)際意義
     第二個(gè)參數(shù):隊(duì)列類型
     DISPATCH_QUEUE_CONCURRENT 并行隊(duì)列
     DISPATCH_QUEUE_SERIAL 串行隊(duì)列
     */
   dispatch_queue_t queue= dispatch_queue_create("123", DISPATCH_QUEUE_CONCURRENT);//方法一
    /*
     第一個(gè)參數(shù):隊(duì)列優(yōu)先級(jí)
     第二個(gè)參數(shù):暫時(shí)無(wú)用浅妆,寫0即可
     */
    dispatch_queue_t queue=dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);//方法二望迎,獲得全局并發(fā)隊(duì)列
    
  //2.封裝任務(wù),添加任務(wù)到隊(duì)列中
    /*
     第一個(gè)參數(shù):隊(duì)列
     第二個(gè)參數(shù):要執(zhí)行的任務(wù)
     */
    dispatch_async(queue, ^{
        
    });
? 并發(fā)隊(duì)列 串行隊(duì)列 主隊(duì)列
異步函數(shù) 會(huì)開啟多條線程凌外,隊(duì)列中的任務(wù)是并發(fā)執(zhí)行 會(huì)開啟線程辩尊,開一條線程,隊(duì)列中的任務(wù)是串行執(zhí)行 不會(huì)開啟線程康辑,所有任務(wù)都在主線程中執(zhí)行摄欲,隊(duì)列中的任務(wù)是串行執(zhí)行
同步函數(shù) 不會(huì)開啟線程,隊(duì)列中的任務(wù)是串行執(zhí)行 不會(huì)開啟線程疮薇,隊(duì)列中的任務(wù)是串行執(zhí)行 在主線程中會(huì)產(chǎn)生死鎖胸墙,在子線程中沒(méi)有影響
  • 并發(fā)隊(duì)列
    兩種創(chuàng)建方法:
    1.自己創(chuàng)建
dispatch_queue_t queue= dispatch_queue_create("123", DISPATCH_QUEUE_CONCURRENT);

2.獲得全局并發(fā)隊(duì)列

dispatch_queue_t queue1=dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
  • 串行隊(duì)列
    兩種創(chuàng)建方法
    1.自己創(chuàng)建
dispatch_queue_t queue= dispatch_queue_create("123", DISPATCH_QUEUE_SERIAL);

2.獲得主隊(duì)列(和主線程相關(guān)的隊(duì)列)

dispatch_queue_t queue1=dispatch_get_main_queue();
  • 主隊(duì)列是gcd自帶的一種特殊的串行隊(duì)列

  • 放在主隊(duì)列中的任務(wù),都會(huì)放到主線程中執(zhí)行

  • 主隊(duì)列特點(diǎn)
    如果主隊(duì)列發(fā)現(xiàn)當(dāng)前主線程有任務(wù)在執(zhí)行按咒,那么主隊(duì)列會(huì)暫停調(diào)用隊(duì)列中的任務(wù)劳秋,直到主線程空閑位置

  • gcd實(shí)現(xiàn)線程間通信
    gcd同步/異步函數(shù)嵌套使用同步/異步函數(shù)

  • gcd的常用函數(shù)

  1. 延遲執(zhí)行
    /*
     第一個(gè)參數(shù):DISPATCH_TIME_NOW 從現(xiàn)在開始計(jì)算時(shí)間
     第二個(gè)參數(shù):延遲的時(shí)間 gcd時(shí)間單位:納秒
     第三個(gè)參數(shù):隊(duì)列
     */
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(1 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
        
    });
  1. 一次性代碼,不能放在懶加載中胖齐,主要用在單例中
   static dispatch_once_t onceToken;
   dispatch_once(&onceToken, ^{
       
   });
  1. gcd柵欄函數(shù)
    3.1 作用:控制多線程中并發(fā)任務(wù)的執(zhí)行順序玻淑,比如放置在任務(wù)1,任務(wù)2之后呀伙,任務(wù)3之前补履,則結(jié)果是等任務(wù)1,2都執(zhí)行完畢后剿另,再執(zhí)行任務(wù)3
    3.2 注意:柵欄函數(shù)不能使用全局并發(fā)隊(duì)列
    /*
     第一個(gè)參數(shù):隊(duì)列
     第二個(gè)參數(shù):操作
     */
    dispatch_barrier_async(queue, ^{
        //操作
    });
  1. gcd快速迭代(遍歷)
    for循環(huán)是同步的箫锤,gcd是開子線程和主線程一起完成遍歷任務(wù),任務(wù)的執(zhí)行是并發(fā)的
    /*
     第一個(gè)參數(shù):遍歷的次數(shù)
     第二個(gè)參數(shù):隊(duì)列(只能傳并發(fā)隊(duì)列雨女,串行隊(duì)列無(wú)效果谚攒,主隊(duì)列會(huì)死鎖)
     第三個(gè)參數(shù):index 索引
     */
    dispatch_apply(10, dispatch_get_global_queue(0, 0), ^(size_t index) {
        NSLog(@"%zd",index);
    });
  1. gcd隊(duì)列組
    gcd隊(duì)列組的使用
    dispatch_queue_t queue2=dispatch_queue_create("queue1", DISPATCH_QUEUE_CONCURRENT);
    dispatch_group_t group=dispatch_group_create();
    /*
     作用:
     第一個(gè):封裝任務(wù)
     第二個(gè):把任務(wù)添加到隊(duì)列中
     第三個(gè):會(huì)監(jiān)聽(tīng)任務(wù)的執(zhí)行情況,通知group
     */
    dispatch_group_async(group, queue2, ^{
        
    });
    dispatch_group_async(group, queue2, ^{
        
    });
    dispatch_group_async(group, queue2, ^{
        
    });
    //攔截通知氛堕,當(dāng)隊(duì)列組中所有的任務(wù)都執(zhí)行完畢的時(shí)候進(jìn)入到下面的方法
    //內(nèi)部本身是異步的
    dispatch_group_notify(group, queue2, ^{
        
    });

老式寫法

    dispatch_queue_t queue3=dispatch_queue_create("queue1", DISPATCH_QUEUE_CONCURRENT);
    dispatch_group_t group1=dispatch_group_create();
    //在該方法后面的異步任務(wù)會(huì)被納入到隊(duì)列組的監(jiān)聽(tīng)范圍馏臭,進(jìn)入群組
    //enter和leave必須配套出現(xiàn)
    dispatch_group_enter(group1);
    dispatch_sync(queue3, ^{
        //離開群組
        dispatch_group_leave(group1);
    });
    
    dispatch_group_enter(group1);
    dispatch_sync(queue3, ^{
        //離開群組
        dispatch_group_leave(group1);
    });
    
    //等待 等價(jià)于dispatch_group_notify,本身是阻塞的,即我不執(zhí)行讼稚,下面的也不執(zhí)行
    //DISPATCH_TIME_FOREVER 表示死等括儒,直到隊(duì)列組中所有的任務(wù)都執(zhí)行完畢之后才執(zhí)行绕沈,
    dispatch_group_wait(group1, DISPATCH_TIME_FOREVER);

NSOperation

  • 作用:
    配合使用NSOperation和NSOperationQueue也能實(shí)現(xiàn)多線程編程

  • 具體步驟:
    1.先將需要執(zhí)行的操作封裝到一個(gè)NSOperation對(duì)象中
    2.將NSOperation對(duì)象添加到NSOperationQueue中
    3.系統(tǒng)會(huì)自動(dòng)將NSOperationQueue中的NSOperation取出來(lái)
    4.將取出的NSOperation封裝的操作放到一條新線程中執(zhí)行

  • NSOperation的子類
    NSOperation是個(gè)抽象類,并不具備封裝操作的能力帮寻,必須使用他的子類

  • 使用NSOperation子類的方式有3中
    1.NSInvocationOperation

//1.創(chuàng)建操作乍狐,封裝任務(wù)
    /*
     第一個(gè)參數(shù):目標(biāo)對(duì)象
     第二個(gè):調(diào)用的方法
     第三個(gè):調(diào)用的方法的參數(shù)
     */
    NSInvocationOperation *op1=[[NSInvocationOperation alloc]initWithTarget:self selector:@selector(run) object:nil];

2.NSBlockOperation

//1.創(chuàng)建操作,封裝任務(wù)
NSBlockOperation *op2=[NSBlockOperation blockOperationWithBlock:^{
        //任務(wù)
    }];
//追加任務(wù)
    //注意:如果一個(gè)操作中的任務(wù)數(shù)量大于1固逗,那么會(huì)開子線程并發(fā)執(zhí)行任務(wù)
    //注意:不一定是子線程浅蚪,有可能是主線程
    [op2 addExecutionBlock:^{
        //任務(wù)
    }];

3.自定義子類繼承NSOperation,實(shí)現(xiàn)內(nèi)部的main方法

//告知要執(zhí)行的任務(wù)是什么
//有利于代碼隱蔽烫罩,有益于代碼復(fù)用
-(void)main{
   //任務(wù)
}

創(chuàng)建好操作后

//2.啟動(dòng)/執(zhí)行操作
//注意:如果直接start掘鄙,那么不會(huì)創(chuàng)建新線程,就和一般的[self 方法名];效果一樣嗡髓,無(wú)法實(shí)現(xiàn)多線程編程
    [op1 start];
    [op2 start];
//2.創(chuàng)建隊(duì)列,這樣才可能實(shí)現(xiàn)多線程編程
    /*
     主隊(duì)列:[NSOperationQueue mainQueue]和gcd中的主隊(duì)列一樣收津,是串行隊(duì)列饿这,在主線程中執(zhí)行
     非主隊(duì)列:[[NSOperationQueue alloc]init]非常特殊,因?yàn)橥瑫r(shí)具備并發(fā)和串行的功能
     默認(rèn)情況下撞秋,非主隊(duì)列是一個(gè)并發(fā)隊(duì)列
     */
    
    NSOperationQueue *queue=[[NSOperationQueue alloc]init];
    //3. 添加操作到隊(duì)列中,內(nèi)部已經(jīng)調(diào)用了start方法
    [queue addOperation:op2];
    
    //簡(jiǎn)便方法   首先創(chuàng)建了NSBlockOperation操作长捧,然后把操作添加到隊(duì)列里
    [queue addOperationWithBlock:^{
        
    }];

NSOperation的其他用法

NSOperationQueue *queue1=[[NSOperationQueue alloc]init];
    //設(shè)置最大并發(fā)數(shù):同一時(shí)間最多有多少個(gè)操作/任務(wù)可以執(zhí)行
    //設(shè)置為1則為串行隊(duì)列,但是不等于只開一條線程
    //不能設(shè)置為0吻贿,因?yàn)闀?huì)不執(zhí)行任務(wù)
    //大于1就是并發(fā)隊(duì)列
    //設(shè)置為-1則代表最大值串结,不受限制
    queue.maxConcurrentOperationCount=5;
    //暫停 可以恢復(fù) 不能暫停當(dāng)前正在執(zhí)行的任務(wù),需要等當(dāng)前任務(wù)執(zhí)行完畢再暫停
    //隊(duì)列中的任務(wù)也是有狀態(tài)的  已經(jīng)執(zhí)行完畢/正在執(zhí)行/排隊(duì)等待執(zhí)行
    [queue setSuspended:YES];
    //繼續(xù)
    [queue setSuspended:NO];
    //取消  不可以恢復(fù) 不能暫停當(dāng)前正在執(zhí)行的任務(wù)舅列,需要等當(dāng)前任務(wù)執(zhí)行完畢再暫停
    //該方法內(nèi)部調(diào)用了所有操作的cancel方法
    //自定義NSOperation
    gh *op3=[[gh alloc]init];
//需要先在自定義的gh中的main方法中設(shè)置
    if (op3.isCancelled==YES) {
        return;
    }
    [queue cancelAllOperations];

NSOperation操作依賴和監(jiān)聽(tīng)

   //添加操作依賴
    //注意:不能循環(huán)依賴肌割,不會(huì)崩潰,但是誰(shuí)都不會(huì)執(zhí)行  可以跨隊(duì)列依賴
    [op1 addDependency:op2];
    [op2 addDependency:op3];
    
    //操作監(jiān)聽(tīng)
    op3.completionBlock = ^{
        //操作
    };

NSOperation實(shí)現(xiàn)線程間通信

NSOperationQueue *queue3=[[NSOperationQueue alloc]init];
 NSBlockOperation *down=[NSBlockOperation blockOperationWithBlock:^{
        
        //操作
        
        //在主線程中更新UI
        [[NSOperationQueue mainQueue]addOperationWithBlock:^{
            //在主線程操作UI更新
        }];
    }];
    
    [queue3 addOperation:down];

以上差不多就是iOS中多線程的知識(shí)點(diǎn)了 帐要,如果哪里有錯(cuò)誤把敞,還希望告知一下

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市榨惠,隨后出現(xiàn)的幾起案子奋早,更是在濱河造成了極大的恐慌,老刑警劉巖赠橙,帶你破解...
    沈念sama閱讀 206,839評(píng)論 6 482
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件耽装,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡期揪,警方通過(guò)查閱死者的電腦和手機(jī)掉奄,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,543評(píng)論 2 382
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)凤薛,“玉大人挥萌,你說(shuō)我怎么就攤上這事绰姻。” “怎么了引瀑?”我有些...
    開封第一講書人閱讀 153,116評(píng)論 0 344
  • 文/不壞的土叔 我叫張陵狂芋,是天一觀的道長(zhǎng)。 經(jīng)常有香客問(wèn)我憨栽,道長(zhǎng)帜矾,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 55,371評(píng)論 1 279
  • 正文 為了忘掉前任屑柔,我火速辦了婚禮屡萤,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘掸宛。我一直安慰自己死陆,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 64,384評(píng)論 5 374
  • 文/花漫 我一把揭開白布唧瘾。 她就那樣靜靜地躺著措译,像睡著了一般。 火紅的嫁衣襯著肌膚如雪饰序。 梳的紋絲不亂的頭發(fā)上领虹,一...
    開封第一講書人閱讀 49,111評(píng)論 1 285
  • 那天,我揣著相機(jī)與錄音求豫,去河邊找鬼塌衰。 笑死,一個(gè)胖子當(dāng)著我的面吹牛蝠嘉,可吹牛的內(nèi)容都是我干的最疆。 我是一名探鬼主播,決...
    沈念sama閱讀 38,416評(píng)論 3 400
  • 文/蒼蘭香墨 我猛地睜開眼蚤告,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼肚菠!你這毒婦竟也來(lái)了?” 一聲冷哼從身側(cè)響起罩缴,我...
    開封第一講書人閱讀 37,053評(píng)論 0 259
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤蚊逢,失蹤者是張志新(化名)和其女友劉穎,沒(méi)想到半個(gè)月后箫章,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體烙荷,經(jīng)...
    沈念sama閱讀 43,558評(píng)論 1 300
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,007評(píng)論 2 325
  • 正文 我和宋清朗相戀三年檬寂,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了终抽。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 38,117評(píng)論 1 334
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖昼伴,靈堂內(nèi)的尸體忽然破棺而出匾旭,到底是詐尸還是另有隱情,我是刑警寧澤圃郊,帶...
    沈念sama閱讀 33,756評(píng)論 4 324
  • 正文 年R本政府宣布价涝,位于F島的核電站,受9級(jí)特大地震影響持舆,放射性物質(zhì)發(fā)生泄漏色瘩。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,324評(píng)論 3 307
  • 文/蒙蒙 一逸寓、第九天 我趴在偏房一處隱蔽的房頂上張望居兆。 院中可真熱鬧,春花似錦竹伸、人聲如沸泥栖。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,315評(píng)論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)吧享。三九已至,卻和暖如春生巡,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背见妒。 一陣腳步聲響...
    開封第一講書人閱讀 31,539評(píng)論 1 262
  • 我被黑心中介騙來(lái)泰國(guó)打工孤荣, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人须揣。 一個(gè)月前我還...
    沈念sama閱讀 45,578評(píng)論 2 355
  • 正文 我出身青樓盐股,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親耻卡。 傳聞我的和親對(duì)象是個(gè)殘疾皇子疯汁,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 42,877評(píng)論 2 345