最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

IOS多線(xiàn)程編程的3種實(shí)現(xiàn)方法

 更新時(shí)間:2015年11月23日 09:40:49   投稿:hebedich  
這篇文章主要介紹了IOS多線(xiàn)程編程的3種實(shí)現(xiàn)方法的相關(guān)資料,需要的朋友可以參考下

前言

在多線(xiàn)程簡(jiǎn)介中,我已經(jīng)說(shuō)明過(guò)了,為了提高界面的流暢度以及用戶(hù)體驗(yàn)。我們務(wù)必要把耗時(shí)的操作放到別的線(xiàn)程中去執(zhí)行,千萬(wàn)不要阻塞主線(xiàn)程。
iOS中有以下3種多線(xiàn)程編程方法:

NSThread
Grand Centeral Dispatch(GCD)
NSOperation和NSOperationQueue

1.NSThread

這是最輕量級(jí)的多線(xiàn)程的方法,使用起來(lái)最直觀(guān)的多線(xiàn)程編程方法。但是因?yàn)樾枰约汗芾砭€(xiàn)程的生命周期,線(xiàn)程同步。經(jīng)常使用NSThread進(jìn)行調(diào)試,在實(shí)際項(xiàng)目中不推薦使用。

//獲取當(dāng)前線(xiàn)程
NSThread *current = [NSThread currentThread];
//獲取主線(xiàn)程
NSThread *main = [NSThread mainThread];

NSLog(@"當(dāng)前線(xiàn)程 --- %@",current);
NSLog(@"主線(xiàn)程 --- %@",main);

控制臺(tái)輸出結(jié)果:

2015-11-22 22:30:29.572 多線(xiàn)程demo[1289:2925847] 當(dāng)前線(xiàn)程 --- <NSThread: 0x7fc0e1401dc0>{number = 1, name = main}
2015-11-22 22:30:29.572 多線(xiàn)程demo[1289:2925847] 主線(xiàn)程 --- <NSThread: 0x7fc0e1401dc0>{number = 1, name = main}
從結(jié)果我們看出當(dāng)前的線(xiàn)程就是主線(xiàn)程,number相當(dāng)于線(xiàn)程的id,name是線(xiàn)程的名稱(chēng),主線(xiàn)程的number就是1

阻塞線(xiàn)程:

//阻塞線(xiàn)程3秒
[NSThread sleepForTimeInterval:3];
[NSThread sleepUntilDate:[NSDate dateWithTimeIntervalSinceNow:3]];

2.GCD(Grand Central Dispatch)

GCD是基于C語(yǔ)言底層API實(shí)現(xiàn)的一套多線(xiàn)程并發(fā)機(jī)制,非常的靈活方便,在實(shí)際的開(kāi)發(fā)中使用很廣泛。
簡(jiǎn)單來(lái)說(shuō)CGD就是把操作放在隊(duì)列中去執(zhí)行。
你只需定義好操作和隊(duì)列就可以了,不需要直接控制線(xiàn)程的創(chuàng)建和銷(xiāo)毀,線(xiàn)程的生命周期由隊(duì)列來(lái)管理。

隊(duì)列:負(fù)責(zé)操作的調(diào)度和執(zhí)行,有先進(jìn)先出(FIFO)的特點(diǎn)。也就是說(shuō)先加入隊(duì)列的操作先執(zhí)行,后加入的后執(zhí)行。

隊(duì)列有兩種:

串行隊(duì)列:

隊(duì)列中的操作只會(huì)按順序執(zhí)行,你可以想象成單窗口排隊(duì)。


并行隊(duì)列:

隊(duì)列中的操作可能會(huì)并發(fā)執(zhí)行,這取決與操作的類(lèi)型,你可以想象成多窗口排隊(duì)。

復(fù)制代碼 代碼如下:
//創(chuàng)建串行隊(duì)列
dispatch_queue_t q = dispatch_queue_create("my_serial_queue", DISPATCH_QUEUE_SERIAL);
//創(chuàng)建并行隊(duì)列
dispatch_queue_t q = dispatch_queue_create("my_concurrent_queue", DISPATCH_QUEUE_CONCURRENT);

my_serial_queue和my_concurrent_queue是隊(duì)列的名字標(biāo)簽,為了與其他的隊(duì)列區(qū)分,在一個(gè)項(xiàng)目里面必須是唯一的。
DISPATCH_QUEUE_SERIAL表示串行隊(duì)列
DISPATCH_QUEUE_CONCURRENT表示并行隊(duì)列

操作同樣也分兩種類(lèi)型:
同步操作:只會(huì)按順序執(zhí)行,執(zhí)行順序是確定的。
異步操作:在串行隊(duì)列中執(zhí)行順序確定,在并行隊(duì)列中執(zhí)行順序不確定

使用block來(lái)定義操作要執(zhí)行的代碼,q是已經(jīng)定義好的,操作要加入的隊(duì)列

//定義同步操作
dispatch_sync(q, ^{
  //要執(zhí)行的代碼  
});
//定義異步操作
dispatch_async(q, ^{
  //要執(zhí)行的代碼   
});

下面我們看一下同步,異步操作加入到串行和并行隊(duì)列里面,執(zhí)行的順序和特點(diǎn):
1.同步操作不管加入到何種隊(duì)列,只會(huì)在主線(xiàn)程按順序執(zhí)行

dispatch_queue_t q_serial = dispatch_queue_create("my_serial_queue", DISPATCH_QUEUE_SERIAL);
dispatch_queue_t q_concurrent = dispatch_queue_create("my_concurrent_queue", DISPATCH_QUEUE_CONCURRENT);
for (int i = 0; i < 5; ++i) {
  dispatch_sync(q_serial, ^{
    NSLog(@"串行隊(duì)列里的同步任務(wù) %@ %d", [NSThread currentThread], i);
  });
}
for (int i = 0; i < 5; ++i) {
  dispatch_sync(q_concurrent, ^{
    NSLog(@"并行隊(duì)列里的同步任務(wù) %@ %d", [NSThread currentThread], i);
  });
}

下面是控制臺(tái)輸出結(jié)果:

2015-11-23 00:40:36.862 01.GCD演練[1952:3613752] 串行隊(duì)列里的同步任務(wù) <NSThread: 0x7ff833505450>{number = 1, name = main} 0
2015-11-23 00:40:36.863 01.GCD演練[1952:3613752] 串行隊(duì)列里的同步任務(wù) <NSThread: 0x7ff833505450>{number = 1, name = main} 1
2015-11-23 00:40:36.863 01.GCD演練[1952:3613752] 串行隊(duì)列里的同步任務(wù) <NSThread: 0x7ff833505450>{number = 1, name = main} 2
2015-11-23 00:40:36.863 01.GCD演練[1952:3613752] 串行隊(duì)列里的同步任務(wù) <NSThread: 0x7ff833505450>{number = 1, name = main} 3
2015-11-23 00:40:36.863 01.GCD演練[1952:3613752] 串行隊(duì)列里的同步任務(wù) <NSThread: 0x7ff833505450>{number = 1, name = main} 4
2015-11-23 00:40:36.863 01.GCD演練[1952:3613752] 并行隊(duì)列里的同步任務(wù) <NSThread: 0x7ff833505450>{number = 1, name = main} 0
2015-11-23 00:40:36.863 01.GCD演練[1952:3613752] 并行隊(duì)列里的同步任務(wù) <NSThread: 0x7ff833505450>{number = 1, name = main} 1
2015-11-23 00:40:36.863 01.GCD演練[1952:3613752] 并行隊(duì)列里的同步任務(wù) <NSThread: 0x7ff833505450>{number = 1, name = main} 2
2015-11-23 00:40:36.864 01.GCD演練[1952:3613752] 并行隊(duì)列里的同步任務(wù) <NSThread: 0x7ff833505450>{number = 1, name = main} 3
2015-11-23 00:40:36.864 01.GCD演練[1952:3613752] 并行隊(duì)列里的同步任務(wù) <NSThread: 0x7ff833505450>{number = 1, name = main} 4

2.異步操作只在非主線(xiàn)程的線(xiàn)程執(zhí)行,在串行隊(duì)列中異步操作會(huì)在新建的線(xiàn)程中按順序執(zhí)行。

復(fù)制代碼 代碼如下:
    dispatch_queue_t q_serial = dispatch_queue_create("my_serial_queue", DISPATCH_QUEUE_SERIAL);
    for(int i = 0; i < 5; ++i){
        dispatch_async(q_serial, ^{
            NSLog(@"串行隊(duì)列 -- 異步任務(wù) %@ %d", [NSThread currentThread], i);
        });
    }

因?yàn)槭钱惒讲僮?,所以?huì)新建一個(gè)線(xiàn)程。又因?yàn)榧尤氲酱嘘?duì)列中,所以所有的操作只會(huì)按順序執(zhí)行。

2015-11-23 01:03:22.372 01.GCD演練[2081:3627139] 串行隊(duì)列 -- 異步任務(wù) <NSThread: 0x7fb593d42f50>{number = 2, name = (null)} 0
2015-11-23 01:03:23.373 01.GCD演練[2081:3627139] 串行隊(duì)列 -- 異步任務(wù) <NSThread: 0x7fb593d42f50>{number = 2, name = (null)} 1
2015-11-23 01:03:24.374 01.GCD演練[2081:3627139] 串行隊(duì)列 -- 異步任務(wù) <NSThread: 0x7fb593d42f50>{number = 2, name = (null)} 2
2015-11-23 01:03:25.375 01.GCD演練[2081:3627139] 串行隊(duì)列 -- 異步任務(wù) <NSThread: 0x7fb593d42f50>{number = 2, name = (null)} 3
2015-11-23 01:03:26.376 01.GCD演練[2081:3627139] 串行隊(duì)列 -- 異步任務(wù) <NSThread: 0x7fb593d42f50>{number = 2, name = (null)} 4

3.異步操作,并行隊(duì)列

復(fù)制代碼 代碼如下:
    dispatch_queue_t q_concurrent = dispatch_queue_create("my_concurrent_queue", DISPATCH_QUEUE_CONCURRENT);
    for(int i = 0; i < 5; ++i){
        dispatch_async(q_concurrent, ^{
            NSLog(@"并行隊(duì)列 -- 異步任務(wù) %@ %d", [NSThread currentThread], i);
        });
    }

理論上并行隊(duì)列會(huì)給每一個(gè)異步操作新建線(xiàn)程,然后讓所有的任務(wù)并發(fā)執(zhí)行。但是實(shí)際上系統(tǒng)能創(chuàng)建的線(xiàn)程數(shù)量是有限的,當(dāng)創(chuàng)建的線(xiàn)程達(dá)到最大線(xiàn)程數(shù)以后,后面的異步操作就需要等待前面的操作執(zhí)行完畢才能得到執(zhí)行。哪個(gè)線(xiàn)程操作執(zhí)行完畢,就把等待的異步任務(wù)安排到哪個(gè)線(xiàn)程。直到所有的操作執(zhí)行完畢。
你可以把上述代碼的循環(huán)次數(shù)改成5000就可以觀(guān)察到此現(xiàn)象。
2015-11-23 01:14:15.282 01.GCD演練[2165:3634728] 并行隊(duì)列 -- 異步任務(wù) <NSThread: 0x7fb3b841b0a0>{number = 4, name = (null)} 3
2015-11-23 01:14:15.282 01.GCD演練[2165:3634724] 并行隊(duì)列 -- 異步任務(wù) <NSThread: 0x7fb3b8514da0>{number = 3, name = (null)} 0
2015-11-23 01:14:15.282 01.GCD演練[2165:3634726] 并行隊(duì)列 -- 異步任務(wù) <NSThread: 0x7fb3b8604db0>{number = 5, name = (null)} 2
2015-11-23 01:14:15.282 01.GCD演練[2165:3634725] 并行隊(duì)列 -- 異步任務(wù) <NSThread: 0x7fb3b86119d0>{number = 2, name = (null)} 1
2015-11-23 01:14:15.285 01.GCD演練[2165:3634729] 并行隊(duì)列 -- 異步任務(wù) <NSThread: 0x7fb3b87011f0>{number = 6, name = (null)} 4

3.NSOperation & NSOperationQueue

雖然GCD的功能已經(jīng)很強(qiáng)大了,但是它使用的API依然是C語(yǔ)言的。在某些時(shí)候,在面向?qū)ο蟮膐bjective-c中使用起來(lái)非常的不方便和不安全。

所以蘋(píng)果公司把GCD中的操作抽象成NSOperation對(duì)象,把隊(duì)列抽象成NSOperationQueue對(duì)象。


抽象為NSOperation & NSOperationQueue以后的好處有一下幾點(diǎn):

代碼風(fēng)格統(tǒng)一了,我們不用在面向?qū)ο蟮膐bjective-C中寫(xiě)面對(duì)過(guò)程的C語(yǔ)言代碼了。
我們知道在GCD中操作的執(zhí)行代碼都是寫(xiě)在匿名的block里面,那么我們很難做到給操作設(shè)置依賴(lài)關(guān)系以及取消操作。這些功能都已經(jīng)封裝到NSOperation對(duì)象里面了。^-^
NSOperationQueue對(duì)象比GCD中隊(duì)列更加的強(qiáng)大和靈活,比如:設(shè)置并發(fā)操作數(shù)量,取消隊(duì)列中所有操作。
NSOperation分為NSInvocationOperation和NSBlockOperation

NSInvocationOperation的使用

//首先定義一個(gè)NSOperationQueue對(duì)象
NSOperationQueue *queue = [[NSOperationQueue alloc] init];
NSInvocationOperation *op = [[NSInvocationOperation alloc] initWithTarget:self selector:@selector(operationAction:) object:@"這里可以穿參數(shù)"];
[queue addOperation:op];//把操作加入隊(duì)列中即開(kāi)始執(zhí)行
- (void)operationAction:(id)obj
{
  NSLog(@"%@ - obj : %@", [NSThread currentThread], obj);
}

輸出為:

2015-11-23 02:55:19.067 多線(xiàn)程demo[2604:3686934] <NSThread: 0x7f9dfa443510>{number = 2, name = (null)} - obj : 這里可以穿參數(shù)
NSBlockOperation的使用

NSOperationQueue *queue = [[NSOperationQueue alloc] init];
NSBlockOperation *op = [NSBlockOperation blockOperationWithBlock:^{
    [self operationAction:@"這是NSBlockOperation"];
}];
[queue addOperation:op];
輸出為:

2015-11-23 02:56:11.812 多線(xiàn)程demo[2617:3687872] <NSThread: 0x7fa983f10a50>{number = 2, name = (null)} - obj : 這是NSBlockOperation
設(shè)置依賴(lài)關(guān)系(執(zhí)行順序)

    NSOperationQueue *queue = [[NSOperationQueue alloc] init];
    NSInvocationOperation *op1 = [[NSInvocationOperation alloc] initWithTarget:self selector:@selector(operationAction:) object:@"op1"];
    NSInvocationOperation *op2 = [[NSInvocationOperation alloc] initWithTarget:self selector:@selector(operationAction:) object:@"op2"];
    //op2在op1之后執(zhí)行
    [op2 addDependency:op1];//這里需要注意,一定要在addOperation之前設(shè)置依賴(lài)關(guān)系
   
    [queue addOperation:op1];
    [queue addOperation:op2];
輸出為:

2015-11-23 02:57:40.283 多線(xiàn)程demo[2661:3689737] <NSThread: 0x7fb663e132d0>{number = 2, name = (null)} - obj : op1
2015-11-23 02:57:40.284 多線(xiàn)程demo[2661:3689737] <NSThread: 0x7fb663e132d0>{number = 2, name = (null)} - obj : op2
沒(méi)有設(shè)置依賴(lài)關(guān)系的輸出:

2015-11-23 03:00:45.939 多線(xiàn)程demo[2709:3692307] <NSThread: 0x7fe951d0d8a0>{number = 2, name = (null)} - obj : op2
2015-11-23 03:00:45.939 多線(xiàn)程demo[2709:3692308] <NSThread: 0x7fe951c24720>{number = 3, name = (null)} - obj : op1
到這里你應(yīng)該發(fā)現(xiàn)了,在NSOperation & NSOperationQueue中,我們不需要再像GCD那樣定義操作的類(lèi)型和隊(duì)列的類(lèi)型和控制操作的執(zhí)行順序了,你只需要直接設(shè)定操作的執(zhí)行順序就可以了。

相關(guān)文章

  • iOS 正則表達(dá)式判斷手機(jī)號(hào)碼、固話(huà)

    iOS 正則表達(dá)式判斷手機(jī)號(hào)碼、固話(huà)

    本文主要介紹了iOS 正則表達(dá)式判斷手機(jī)號(hào)碼、固話(huà),以及匹配是否是移動(dòng)/聯(lián)通/電信手機(jī)號(hào)的方法。具有很好的參考價(jià)值,下面跟著小編一起來(lái)看下吧
    2017-03-03
  • iOS 禁止按鈕在一定時(shí)間內(nèi)連續(xù)點(diǎn)擊

    iOS 禁止按鈕在一定時(shí)間內(nèi)連續(xù)點(diǎn)擊

    本文主要介紹了iOS中禁止按鈕在一定時(shí)間內(nèi)連續(xù)點(diǎn)擊的方法,具有很好的參考價(jià)值,下面跟著小編一起來(lái)看下吧
    2017-02-02
  • iOS實(shí)現(xiàn)類(lèi)似格瓦拉電影的轉(zhuǎn)場(chǎng)動(dòng)畫(huà)

    iOS實(shí)現(xiàn)類(lèi)似格瓦拉電影的轉(zhuǎn)場(chǎng)動(dòng)畫(huà)

    這篇文章主要給大家介紹了利用iOS如何實(shí)現(xiàn)類(lèi)似格瓦拉電影的轉(zhuǎn)場(chǎng)動(dòng)畫(huà),文中給出了詳細(xì)步驟實(shí)現(xiàn)代碼,對(duì)大家的學(xué)習(xí)和理解很有幫助,有需要的朋友們可以參考借鑒,下面來(lái)一起看看吧。
    2016-11-11
  • iOS輕松實(shí)現(xiàn)導(dǎo)航欄透明漸變

    iOS輕松實(shí)現(xiàn)導(dǎo)航欄透明漸變

    這篇文章主要為大家詳細(xì)介紹了iOS輕松實(shí)現(xiàn)導(dǎo)航欄透明漸變效果,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2017-01-01
  • iOS中block的定義與使用

    iOS中block的定義與使用

    蘋(píng)果官方文檔聲明,block是objc對(duì)象。下面這篇文章主要給大家介紹了關(guān)于iOS中block的定義與使用,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)各位iOS開(kāi)發(fā)者具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2019-03-03
  • iOS中UILabel設(shè)置居上對(duì)齊、居中對(duì)齊、居下對(duì)齊及文字置頂顯示

    iOS中UILabel設(shè)置居上對(duì)齊、居中對(duì)齊、居下對(duì)齊及文字置頂顯示

    這篇文章主要給大家介紹了關(guān)于iOS中UILabel如何設(shè)置居上對(duì)齊、居中對(duì)齊、居下對(duì)齊及文字置頂顯示效果的相關(guān)資料,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧。
    2017-12-12
  • 判斷iOS應(yīng)用是否開(kāi)放HTTP權(quán)限的方法

    判斷iOS應(yīng)用是否開(kāi)放HTTP權(quán)限的方法

    這篇文章主要為大家詳細(xì)介紹了判斷iOS應(yīng)用是否開(kāi)放HTTP權(quán)限的方法,感興趣的小伙伴們可以參考一下
    2016-03-03
  • 談一談iOS單例模式

    談一談iOS單例模式

    這篇文章主要和大家談一談iOS中的單例模式,單例模式是一種常用的軟件設(shè)計(jì)模式,想要深入了解iOS單例模式的朋友可以參考一下
    2016-05-05
  • iOS內(nèi)存管理中引用計(jì)數(shù)的學(xué)習(xí)

    iOS內(nèi)存管理中引用計(jì)數(shù)的學(xué)習(xí)

    文章給大家分享了關(guān)于iOS內(nèi)存管理中引用計(jì)數(shù)的相關(guān)知識(shí)點(diǎn),對(duì)此有需要的朋友可以跟著學(xué)習(xí)下。
    2018-05-05
  • MAC 系統(tǒng)安裝java并配置環(huán)境變量

    MAC 系統(tǒng)安裝java并配置環(huán)境變量

    這篇文章主要介紹了MAC 系統(tǒng)安裝java并配置環(huán)境變量的相關(guān)資料,需要的朋友可以參考下
    2017-03-03

最新評(píng)論

洪泽县| 清远市| 礼泉县| 许昌市| 葫芦岛市| 民县| 米脂县| 石景山区| 安溪县| 灵璧县| 大丰市| 抚远县| 和林格尔县| 南岸区| 沾化县| 竹北市| 民和| 德令哈市| 静海县| 廉江市| 灵璧县| 眉山市| 清河县| 拉孜县| 龙江县| 连南| 纳雍县| 精河县| 女性| 普安县| 蕉岭县| 买车| 肥西县| 德钦县| 定边县| 吴江市| 中牟县| 林州市| 邵阳县| 汨罗市| 龙南县|