iOS多線(xiàn)程-GCD

1.基本介紹

什么是GCD

Grand Central Dispatch (GCD) 是異步執(zhí)行任務(wù)的技術(shù)之一框仔。開(kāi)發(fā)者只需要定義想執(zhí)行的任務(wù)并追加到適當(dāng)?shù)腄ispatch Queue中,GCD就能生成必要的線(xiàn)程并計(jì)劃執(zhí)行任務(wù)。

GCD的優(yōu)勢(shì)

  • GCD會(huì)自動(dòng)的利用多核(比如雙核淆攻,四核)
  • GCD會(huì)自動(dòng)管理線(xiàn)程的生命周期(創(chuàng)建線(xiàn)程笋敞、調(diào)度任務(wù)音半、銷(xiāo)毀線(xiàn)程)
  • GCD會(huì)自動(dòng)根據(jù)系統(tǒng)負(fù)載來(lái)增減線(xiàn)程數(shù)量

Dispatch Queues

GCD的基本概念就是dispatch queue琳袄。dispatch queue是一個(gè)對(duì)象,它可以接受任務(wù)澎办,并將任務(wù)以先到先執(zhí)行的順序來(lái)執(zhí)行嘲碱。dispatch queue可以是并發(fā)的或串行的。并發(fā)任務(wù)會(huì)像NSOperationQueue那樣基于系統(tǒng)負(fù)載來(lái)合適地并發(fā)進(jìn)行局蚀,串行隊(duì)列同一時(shí)間只執(zhí)行單一任務(wù)麦锯。

  • 串行隊(duì)列:按FIFO每次取出一個(gè)任務(wù)執(zhí)行,當(dāng)前一個(gè)任務(wù)完成后才會(huì)取出第二個(gè)任務(wù)琅绅。
  • 并發(fā)隊(duì)列:按FIFO取出任務(wù)執(zhí)行扶欣,但是不會(huì)等待前一個(gè)任務(wù)完成就會(huì)取出第二個(gè)任務(wù)。


    SerialQueue.png
ConcurrentQueue.png

任務(wù)

  • 同步任務(wù):同步執(zhí)行,會(huì)阻塞當(dāng)前線(xiàn)程料祠,直到當(dāng)前的block任務(wù)執(zhí)行完畢骆捧。
  • 異步任務(wù):異步執(zhí)行,不會(huì)阻塞當(dāng)前線(xiàn)程髓绽。
隊(duì)列與任務(wù)的組合情況
同步任務(wù) 異步任務(wù)
主隊(duì)列 在主隊(duì)列添加同步任務(wù)會(huì)死鎖 不開(kāi)啟新線(xiàn)程敛苇,在主線(xiàn)程按序執(zhí)行任務(wù)
串行隊(duì)列 不開(kāi)啟新線(xiàn)程,在當(dāng)前線(xiàn)程按序執(zhí)行任務(wù) 開(kāi)啟一條線(xiàn)程顺呕,在這個(gè)線(xiàn)程中按序執(zhí)行任務(wù)
并發(fā)隊(duì)列/全局并發(fā)隊(duì)列 不開(kāi)啟新線(xiàn)程枫攀,在當(dāng)前線(xiàn)程按序執(zhí)行任務(wù) GCD根據(jù)系統(tǒng)資源開(kāi)啟多條線(xiàn)程執(zhí)行任務(wù)

小結(jié)

  1. 同步和異步?jīng)Q定了是否開(kāi)啟新的線(xiàn)程。main隊(duì)列除外株茶,在main隊(duì)列中来涨,同步或者異步執(zhí)行都不會(huì)另開(kāi)線(xiàn)程。
  2. 串行和并行启盛,決定了任務(wù)是否同時(shí)執(zhí)行扫夜。
  3. 不要在執(zhí)行串行隊(duì)列的線(xiàn)程中向當(dāng)前的串行隊(duì)列添加同步任務(wù),會(huì)導(dǎo)致死鎖驰徊。

2.GCD使用

獲取Dispatch Queue的方法有兩種。
第一種方法是通過(guò)GCD的API生成Dispatch Queue堕阔。

dispatch_queue_t queue = dispatch_queue_create("serial_queue", DISPATCH_QUEUE_SERIAL);
dispatch_queue_t queue = dispatch_queue_create("concurrent_queue", DISPATCH_QUEUE_CONCURRENT);

第一個(gè)參數(shù)指定該隊(duì)列的名稱(chēng)棍厂,該名稱(chēng)會(huì)出現(xiàn)應(yīng)用程序崩潰時(shí)產(chǎn)生的CrashLog中,在調(diào)用過(guò)程中我們也可以使用dispatch_queue_get_label(DISPATCH_CURRENT_QUEUE_LABEL)獲取當(dāng)前隊(duì)列的名字超陆。

第二個(gè)參數(shù)指定該隊(duì)列的類(lèi)型牺弹。

DISPATCH_QUEUE_SERIAL或者NULL表示該隊(duì)列是串行隊(duì)列,

DISPATCH_QUEUE_CONCURRENT表示該隊(duì)列是并發(fā)隊(duì)列时呀。

第二種方法是獲取系統(tǒng)標(biāo)準(zhǔn)提供的Dispatch Queue张漂。

系統(tǒng)會(huì)給我們提供Main Dispatch Queue(主隊(duì)列)和Global Dispatch Queue(全局并發(fā)隊(duì)列)。

Main Dispatch Queue
Main Dispatch Queue顧名思義谨娜,是在主線(xiàn)程中執(zhí)行的隊(duì)列航攒。因?yàn)橹骶€(xiàn)程只有一個(gè),所以主隊(duì)列自然就是串行隊(duì)列趴梢。追加到主隊(duì)列的處理在主線(xiàn)程的RunLoop中執(zhí)行漠畜,因此要將用戶(hù)界面的更新等一些必須在主線(xiàn)程中執(zhí)行的處理追加到主隊(duì)列中使用。

// Main 隊(duì)列獲取方法
dispatch_queue_t mainQueue = dispatch_get_main_queue()坞靶;
dispatch_sync(dispatch_get_main_queue(), ^{
        NSLog(@"%s", dispatch_queue_get_label(DISPATCH_CURRENT_QUEUE_LABEL));
    });

在上面說(shuō)過(guò)憔狞,同步會(huì)阻塞當(dāng)前線(xiàn)程,執(zhí)行完block里面任務(wù)才會(huì)繼續(xù)往下走彰阴。dispatch_sync阻塞了主線(xiàn)程瘾敢,然后把任務(wù)追到加主隊(duì)列,并在主線(xiàn)程執(zhí)行,但是此時(shí)的主線(xiàn)程已經(jīng)被阻塞簇抵,所以block任務(wù)也無(wú)法執(zhí)行庆杜,block任務(wù)不執(zhí)行,dispatch_sync會(huì)繼續(xù)阻塞主線(xiàn)程正压。這樣子就產(chǎn)生了死鎖欣福。

Global Dispatch Queue
Global Dispatch Queue是全局并發(fā)隊(duì)列,沒(méi)有必要通過(guò)dispatch_queue_create函數(shù)逐個(gè)生成并發(fā)焦履,只要獲取全局并發(fā)隊(duì)列使用即可拓劝。
全局并發(fā)隊(duì)列有4個(gè)執(zhí)行優(yōu)先級(jí),分別是高優(yōu)先級(jí)(High Priority)嘉裤,默認(rèn)優(yōu)先級(jí)(Default Priority)郑临,低優(yōu)先級(jí)(Low Priority)和后臺(tái)優(yōu)先級(jí)(Background Priority)。

// 獲取高優(yōu)先級(jí)
dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0);
// 獲取默認(rèn)優(yōu)先級(jí)
dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
// 獲取低優(yōu)先級(jí)
dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_LOW, 0);
// 獲取后臺(tái)優(yōu)先級(jí)
dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_BACKGROUND, 0);

dispatch_set_target_queue
dispatch_queue_create函數(shù)生成的隊(duì)列不管是串行隊(duì)列還是并發(fā)隊(duì)列屑宠,都使用跟默認(rèn)優(yōu)先級(jí)的全局并發(fā)隊(duì)列相同的優(yōu)先級(jí)厢洞。而設(shè)置一個(gè)隊(duì)列的優(yōu)先級(jí)可以使用dispatch_set_target_queue。

dispatch_queue_t serialQueue = dispatch_queue_create("com.gcd.serialQueue", NULL);

dispatch_queue_t backgroundGlobalQueue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_BACKGROUND, 0);

dispatch_set_target_queue(serialQueue, backgroundGlobalQueue);

指定要變更優(yōu)先級(jí)的隊(duì)列為第一個(gè)參數(shù)典奉,指定參考隊(duì)列為第二個(gè)參數(shù)躺翻。

dispatch_set_target_queue函數(shù)還可以改變隊(duì)列的執(zhí)行層次。在多個(gè)串行隊(duì)列中卫玖,使用dispatch_set_target_queue函數(shù)指定目標(biāo)為某一串行隊(duì)列公你,那么原本應(yīng)并行執(zhí)行的多個(gè)串行隊(duì)列,在目標(biāo)串行隊(duì)列上只能同時(shí)執(zhí)行一個(gè)任務(wù)假瞬。在必須要將不可并發(fā)執(zhí)行的處理追加到多個(gè)串行隊(duì)列中時(shí)陕靠,可以使用dispatch_set_target_queue函數(shù)防止并發(fā)執(zhí)行。

    dispatch_queue_t serialQueue1 = dispatch_queue_create("serialQueue1", NULL);
    dispatch_queue_t serialQueue2 = dispatch_queue_create("serialQueue2", NULL);
    dispatch_queue_t serialQueue3 = dispatch_queue_create("serialQueue3", NULL);
    dispatch_queue_t serialQueue4 = dispatch_queue_create("serialQueue4", NULL);
    
    dispatch_set_target_queue(serialQueue2, serialQueue1);
    dispatch_set_target_queue(serialQueue3, serialQueue1);
    dispatch_set_target_queue(serialQueue4, serialQueue1);
    
    dispatch_async(serialQueue2, ^{
        NSLog(@"%s",dispatch_queue_get_label(DISPATCH_CURRENT_QUEUE_LABEL));
    });
    dispatch_async(serialQueue3, ^{
        NSLog(@"%s",dispatch_queue_get_label(DISPATCH_CURRENT_QUEUE_LABEL));
    });
    dispatch_async(serialQueue4, ^{
        NSLog(@"%s",dispatch_queue_get_label(DISPATCH_CURRENT_QUEUE_LABEL));
    });

    //輸出結(jié)果為
    serialQueue2
    serialQueue3
    serialQueue4

dispatch_after
想在指定時(shí)間后執(zhí)行的情況脱茉,可使用dispatch_after函數(shù)來(lái)實(shí)現(xiàn)

dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(3 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
        NSLog(@"等待3秒");
    });

使用dispatch_after需要注意的是剪芥,這個(gè)函數(shù)并不是在指定時(shí)間后執(zhí)行,而是在指定時(shí)間把任務(wù)追加到指定的隊(duì)列中琴许。如上面的代碼税肪,3秒后只是把任務(wù)追加到主隊(duì)列當(dāng)中,具體執(zhí)行時(shí)間與主線(xiàn)程擁塞程度有關(guān)榜田。

Dispatch Group
我們經(jīng)常會(huì)有這樣的需求寸认,在多個(gè)追加到Dispatch Queue中的處理執(zhí)行完畢后,進(jìn)行一些操作串慰。在使用串行隊(duì)列的時(shí)候偏塞,我們只需要在最后追加結(jié)束后的處理。但是在使用多個(gè)并發(fā)隊(duì)列或同時(shí)使用多個(gè)隊(duì)列時(shí)邦鲫,就需要使用Dispatch Group灸叼。

    dispatch_queue_t queue = dispatch_get_global_queue(0, 0);
    dispatch_group_t group = dispatch_group_create();
    
    dispatch_group_async(group, queue, ^{
        NSLog(@"block1");
    });
    dispatch_group_async(group, queue, ^{
        NSLog(@"block2");
    });
    dispatch_group_async(group, queue, ^{
        NSLog(@"block3");
    });
    
    dispatch_group_notify(group, queue, ^{
        NSLog(@"done");
    });

    //執(zhí)行結(jié)果
    block1
    block3
    block2
    done

很明顯神汹,這種方式是不阻塞的。由于我們是異步把任務(wù)添加到隊(duì)列中古今,所以任務(wù)執(zhí)行的順序是不一定的屁魏。但是dispatch_group_notify里面的block肯定是最后執(zhí)行。
如果想要阻塞線(xiàn)程可以使用dispatch_group_wait(group, DISPATCH_TIME_FOREVER);第二個(gè)參數(shù)為等待時(shí)間DISPATCH_TIME_FOREVER表示永遠(yuǎn)等待捉腥。

當(dāng)任務(wù)中有completion block時(shí)氓拼,這種任務(wù)是馬上完成的,例如網(wǎng)絡(luò)請(qǐng)求抵碟。但是我們想讓任務(wù)在收到completion block時(shí)才完成桃漾,這時(shí)需要我們手動(dòng)管理任務(wù)的開(kāi)始和結(jié)束。

    dispatch_group_t group = dispatch_group_create();
    
    dispatch_group_enter(group);
    
    [Request requestWithSuccess:^{
        NSLog(@"success");
        dispatch_group_leave(group);
    } failBlk:^{
        NSLog(@"fail");
        dispatch_group_leave(group);
    }];
    
    
    dispatch_group_enter(group);
    
    [Request requestWithSuccess:^{
        NSLog(@"success");
        dispatch_group_leave(group);
    } failBlk:^{
        NSLog(@"fail");
        dispatch_group_leave(group);
    }];
    
    dispatch_notify(group, dispatch_get_main_queue(), ^{
        NSLog(@"全部完成");
    });

通過(guò)dispatch_group_enter拟逮,dispatch_group_leave兩個(gè)函數(shù)可以實(shí)現(xiàn)進(jìn)入,退出兩個(gè)動(dòng)作撬统。要注意enterleave要成對(duì)出現(xiàn),否則group永遠(yuǎn)不會(huì)結(jié)束敦迄。

dispatch_barrier_async
在訪問(wèn)數(shù)據(jù)時(shí)恋追,使用串行隊(duì)列可以避免數(shù)據(jù)競(jìng)爭(zhēng)問(wèn)題。寫(xiě)入處理不可與其他的寫(xiě)入處理以及包含讀取處理的其他某些處理并行執(zhí)行罚屋,但是讀取處理只和讀取處理并行執(zhí)行苦囱,那么多個(gè)并行執(zhí)行就不會(huì)發(fā)生問(wèn)題。也就是說(shuō)脾猛,為了高效率的訪問(wèn)撕彤,需要實(shí)現(xiàn)多讀單寫(xiě)。
GCD為我們提供了一種方便的實(shí)現(xiàn)dispatch_barrier_async尖滚,它等待所有位于barrier函數(shù)之前的操作執(zhí)行完畢后執(zhí)行,并且在barrier函數(shù)執(zhí)行完成后,barrier函數(shù)之后的操作才會(huì)得到執(zhí)行,該函數(shù)需要同dispatch_queue_create函數(shù)生成的并發(fā)隊(duì)列一起使用。

    dispatch_queue_t queue = dispatch_queue_create("queueForBarrier", DISPATCH_QUEUE_CONCURRENT);
    dispatch_async(queue, ^{
        NSLog(@"任務(wù)1");
    });
    dispatch_async(queue, ^{
        NSLog(@"任務(wù)2");
    });
    dispatch_barrier_async(queue, ^{
        [NSThread sleepForTimeInterval:1];
        NSLog(@"任務(wù)3 barrier");
    });
    dispatch_async(queue, ^{
        NSLog(@"任務(wù)4");
    });
    dispatch_async(queue, ^{
        NSLog(@"任務(wù)5");
    });

    //輸出結(jié)果
    任務(wù)2
    任務(wù)1
    任務(wù)3 barrier
    任務(wù)4
    任務(wù)5

dispatch_apply
dispatch_apply函數(shù)按指定的次數(shù)降block追加到指定的隊(duì)列中瞧柔,并阻塞線(xiàn)程等待全部處理執(zhí)行結(jié)束漆弄。

    dispatch_queue_t queue = dispatch_get_global_queue(0, 0);
    NSArray *array = @[@"1",@"2",@"3"];
    dispatch_apply(array.count, queue, ^(size_t index) {
        NSLog(@"%@",array[index]);
    });
    NSLog(@"完成");

    //輸出結(jié)果
    2
    1
    3
    完成

由于dispatch_apply函數(shù)會(huì)等待所有處理執(zhí)行結(jié)束,所以最好在dispatch_async函數(shù)中非同步的執(zhí)行dispatch_apply函數(shù)

    dispatch_queue_t queue = dispatch_get_global_queue(0, 0);
    NSArray *array = @[@"1",@"2",@"3"];
    dispatch_async(queue, ^{
        dispatch_apply(array.count, queue, ^(size_t index) {
            NSLog(@"%@",array[index]);
        });
        
        dispatch_async(dispatch_get_main_queue(), ^{
            //回到主線(xiàn)程
        });
    });

dispatch_suspend/dispatch_resume

    //掛起指定的隊(duì)列
    dispatch_suspend(queue);
    //恢復(fù)指定的隊(duì)列
    dispatch_resume(queue);

dispatch_suspend函數(shù)對(duì)已經(jīng)執(zhí)行的處理沒(méi)有影響造锅,隊(duì)列中未執(zhí)行的處理會(huì)被掛起撼唾,dispatch_resume函數(shù)會(huì)恢復(fù)這些處理的執(zhí)行。

Dispatch Semaphore
信號(hào)量可以控制同時(shí)訪問(wèn)資源的數(shù)量哥蔚,解決資源爭(zhēng)奪的問(wèn)題倒谷。信號(hào)量持有計(jì)數(shù),計(jì)數(shù)為0等待糙箍,計(jì)數(shù)大于或等于1時(shí)渤愁,減去1而不等待。類(lèi)似于過(guò)安檢時(shí)深夯,允許n個(gè)人一起安檢抖格,每當(dāng)一個(gè)人安檢完成诺苹,則下一個(gè)人可以進(jìn)行安檢。

    //創(chuàng)建計(jì)數(shù)值為1的信號(hào)量
    dispatch_semaphore_t semaphore = dispatch_semaphore_create(1);
    dispatch_queue_t queue = dispatch_get_global_queue(0, 0);
    NSArray *array = @[@"1",@"2",@"3",@"4",@"5"];
    for (NSString *string in array) {
        dispatch_async(queue, ^{
            //dispatch_semaphore_wait函數(shù)等待信號(hào)量的計(jì)數(shù)值大于或等于1時(shí)雹拄,對(duì)計(jì)數(shù)減1并向下執(zhí)行收奔,否則等待。
            //DISPATCH_TIME_FOREVER表示永遠(yuǎn)等待滓玖。
            dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER);

            [NSThread sleepForTimeInterval:1
            NSLog(@"%@",string);
            
            //dispatch_semaphore_signal函數(shù)將信號(hào)量的計(jì)數(shù)加1
            dispatch_semaphore_signal(semaphore);
        });
    }

上面代碼創(chuàng)建了一個(gè)計(jì)數(shù)初始值為1的信號(hào)量坪哄,然后向全局并發(fā)隊(duì)列中添加了5個(gè)任務(wù),當(dāng)有一個(gè)任務(wù)通過(guò)dispatch_semaphore_wait函數(shù)時(shí)势篡,信號(hào)量的計(jì)數(shù)被減1翩肌,此時(shí)計(jì)數(shù)為0,剩余的任務(wù)則會(huì)等待殊霞,直到dispatch_semaphore_signal將計(jì)數(shù)加1摧阅。

    dispatch_time_t time = dispatch_time(DISPATCH_TIME_NOW, (int64_t)(3 * NSEC_PER_SEC));
    long result = dispatch_semaphore_wait(semaphore, time);
    if (result == 0) {
        //在等待時(shí)間內(nèi)計(jì)數(shù)值達(dá)到大于等于1,減1繼續(xù)處理
    }
    else{
        //在等待時(shí)間內(nèi)計(jì)數(shù)值為0
    }

我們也可以通過(guò)dispatch_semaphore_wait函數(shù)的返回值進(jìn)行分支處理绷蹲。當(dāng)我們給定一個(gè)等待時(shí)間棒卷,如果信號(hào)量的計(jì)數(shù)值在等待時(shí)間內(nèi)達(dá)到大于等于1,dispatch_semaphore_wait返回0祝钢,如果超過(guò)這個(gè)時(shí)間計(jì)數(shù)值還為0比规,則返回值不為0。

dispatch_once
dispatch_once函數(shù)保證在應(yīng)用程序執(zhí)行中只執(zhí)行一次處理拦英。并且在多線(xiàn)程環(huán)境下能保證安全蜒什。

@implementation Manager

+ (Manager *)sharedInstance
{
    static Manage *manager = nil;
    static dispatch_once_t token;

    dispatch_once(&token, ^{
        manager = [[Manager alloc] init];
    });

    return manager;
}

我們一般用來(lái)創(chuàng)建單例。

Dispatch Source
Dispatch Source的種類(lèi)

名稱(chēng) 種類(lèi)
DISPATCH_SOURCE_TYPE_DATA_ADD 自定義事件疤估,變量增加
DISPATCH_SOURCE_TYPE_DATA_OR 自定義事件灾常,變量OR
DISPATCH_SOURCE_TYPE_MACH_SEND MACH 端口發(fā)送
DISPATCH_SOURCE_TYPE_MACH_RECV MACH 端口接收
DISPATCH_SOURCE_TYPE_PROC 檢測(cè)到與進(jìn)程相關(guān)的事件
DISPATCH_SOURCE_TYPE_READ IO操作,如對(duì)文件的操作铃拇、socket操作的讀響應(yīng)
DISPATCH_SOURCE_TYPE_SIGNAL 接受信號(hào)
DISPATCH_SOURCE_TYPE_TIMER 定時(shí)器
DISPATCH_SOURCE_TYPE_VNODE 文件系統(tǒng)有變更
DISPATCH_SOURCE_TYPE_WRITE IO操作钞瀑,如對(duì)文件的操作、socket操作的寫(xiě)響應(yīng)

使用DISPATCH_SOURCE_TYPE_TIMER的定時(shí)器的例子

    //倒計(jì)時(shí)時(shí)間
    __block int timeout = 60;
    
    //創(chuàng)建隊(duì)列
    dispatch_queue_t queue = dispatch_get_global_queue(0, 0);
    
    //創(chuàng)建timer
    dispatch_source_t timer = dispatch_source_create(DISPATCH_SOURCE_TYPE_TIMER, 0, 0, queue);
    
    //設(shè)置開(kāi)始時(shí)間未當(dāng)前時(shí)間慷荔,間隔1秒雕什,誤差為0
    dispatch_source_set_timer(timer, DISPATCH_TIME_NOW, (int64_t)(1 * NSEC_PER_SEC), 0);
    
    //觸發(fā)事件
    dispatch_source_set_event_handler(timer, ^{
        if (timeout <= 0) {
            //取消dispatch source
            dispatch_source_cancel(timer);
        }
        else{
            timeout --;
            NSLog(@"%d",timeout);
        }
    });
    
    //啟動(dòng)定時(shí)器
    dispatch_resume(timer);
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市显晶,隨后出現(xiàn)的幾起案子贷岸,更是在濱河造成了極大的恐慌,老刑警劉巖磷雇,帶你破解...
    沈念sama閱讀 217,509評(píng)論 6 504
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件偿警,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡唯笙,警方通過(guò)查閱死者的電腦和手機(jī)户敬,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,806評(píng)論 3 394
  • 文/潘曉璐 我一進(jìn)店門(mén)落剪,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái),“玉大人尿庐,你說(shuō)我怎么就攤上這事忠怖。” “怎么了抄瑟?”我有些...
    開(kāi)封第一講書(shū)人閱讀 163,875評(píng)論 0 354
  • 文/不壞的土叔 我叫張陵凡泣,是天一觀的道長(zhǎng)。 經(jīng)常有香客問(wèn)我皮假,道長(zhǎng)鞋拟,這世上最難降的妖魔是什么? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 58,441評(píng)論 1 293
  • 正文 為了忘掉前任惹资,我火速辦了婚禮贺纲,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘褪测。我一直安慰自己猴誊,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,488評(píng)論 6 392
  • 文/花漫 我一把揭開(kāi)白布侮措。 她就那樣靜靜地躺著懈叹,像睡著了一般。 火紅的嫁衣襯著肌膚如雪分扎。 梳的紋絲不亂的頭發(fā)上澄成,一...
    開(kāi)封第一講書(shū)人閱讀 51,365評(píng)論 1 302
  • 那天,我揣著相機(jī)與錄音畏吓,去河邊找鬼墨状。 笑死,一個(gè)胖子當(dāng)著我的面吹牛菲饼,可吹牛的內(nèi)容都是我干的肾砂。 我是一名探鬼主播,決...
    沈念sama閱讀 40,190評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼巴粪,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼通今!你這毒婦竟也來(lái)了粥谬?” 一聲冷哼從身側(cè)響起肛根,我...
    開(kāi)封第一講書(shū)人閱讀 39,062評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎漏策,沒(méi)想到半個(gè)月后派哲,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,500評(píng)論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡掺喻,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,706評(píng)論 3 335
  • 正文 我和宋清朗相戀三年芭届,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了储矩。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 39,834評(píng)論 1 347
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡褂乍,死狀恐怖持隧,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情逃片,我是刑警寧澤屡拨,帶...
    沈念sama閱讀 35,559評(píng)論 5 345
  • 正文 年R本政府宣布,位于F島的核電站褥实,受9級(jí)特大地震影響呀狼,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜损离,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,167評(píng)論 3 328
  • 文/蒙蒙 一哥艇、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧僻澎,春花似錦貌踏、人聲如沸。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 31,779評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)。三九已至拳恋,卻和暖如春凡资,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背谬运。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 32,912評(píng)論 1 269
  • 我被黑心中介騙來(lái)泰國(guó)打工隙赁, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人梆暖。 一個(gè)月前我還...
    沈念sama閱讀 47,958評(píng)論 2 370
  • 正文 我出身青樓伞访,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親轰驳。 傳聞我的和親對(duì)象是個(gè)殘疾皇子厚掷,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,779評(píng)論 2 354

推薦閱讀更多精彩內(nèi)容

  • 一、簡(jiǎn)介在iOS所有實(shí)現(xiàn)多線(xiàn)程的方案中级解,GCD應(yīng)該是最有魅力的冒黑,因?yàn)镚CD本身是蘋(píng)果公司為多核的并行運(yùn)算提出的解決...
    MYS_iOS_8801閱讀 572評(píng)論 0 0
  • 多線(xiàn)程學(xué)習(xí)筆記-GCD 我把這篇文章所用到的代碼總結(jié)到這里->GCD項(xiàng)目總結(jié)下載地址-GCD-wxk可以下載參考 ...
    wxkkkkk閱讀 534評(píng)論 0 2
  • 目錄:iOS多線(xiàn)程(一)--pthread、NSThreadiOS多線(xiàn)程(二)--GCD詳解iOS多線(xiàn)程(三)--...
    Claire_wu閱讀 1,075評(píng)論 0 6
  • 一、基本概念 線(xiàn)程是用來(lái)執(zhí)行任務(wù)的泵殴,線(xiàn)程徹底執(zhí)行完任務(wù)A才能執(zhí)行任務(wù)B涮帘,為了同時(shí)執(zhí)行兩個(gè)任務(wù),產(chǎn)生了多線(xiàn)程 1笑诅、進(jìn)...
    空白Null閱讀 676評(píng)論 0 3
  • 為了能更好的傳播產(chǎn)品經(jīng)理精品文章焚辅,我們特意創(chuàng)建「PM 周刊」,將通過(guò)微信和郵件的形式推送給大家苟鸯,每周周一定時(shí)推送同蜻。...
    四勾4J閱讀 183評(píng)論 0 0