iOS多線程學習

1. GCD的API

/**
 serial(連續的)
 dispatch(分派)
 serialDispatch 一個線程,同時執行的處理只能有一個,按順序執行
 */
void test_serialDispatch(){
    dispatch_queue_t mySerialDispatchQueue = dispatch_queue_create("com.example.gcd.MySerialDispatchQueue", NULL);

    void(^blk_0)(void) = ^() {
        NSLog(@"%s,%d",__func__,__LINE__);
    };
    void(^blk_1)(void) = ^() {
        NSLog(@"%s,%d",__func__,__LINE__);
    };
    void(^blk_2)(void) = ^() {
        NSLog(@"%s,%d",__func__,__LINE__);
    };
    void(^blk_3)(void) = ^() {
        NSLog(@"%s,%d",__func__,__LINE__);
    };
    void(^blk_4)(void) = ^() {
        NSLog(@"%s,%d",__func__,__LINE__);
    };
    void(^blk_5)(void) = ^() {
        NSLog(@"%s,%d",__func__,__LINE__);
    };
    void(^blk_6)(void) = ^() {
        NSLog(@"%s,%d",__func__,__LINE__);
    };
    void(^blk_7)(void) = ^() {
        NSLog(@"%s,%d",__func__,__LINE__);
    };
    dispatch_async(mySerialDispatchQueue, blk_0);
    dispatch_async(mySerialDispatchQueue, blk_1);
    dispatch_async(mySerialDispatchQueue, blk_2);
    dispatch_async(mySerialDispatchQueue, blk_3);
    dispatch_async(mySerialDispatchQueue, blk_4);
    dispatch_async(mySerialDispatchQueue, blk_5);
    dispatch_async(mySerialDispatchQueue, blk_6);
    dispatch_async(mySerialDispatchQueue, blk_7);
    //    dispatch_release(mySerialDispatchQueue);
    NSLog(@"%s,%d",__func__,__LINE__);
}

/**
 concurrent(併發的,同時發生的)
 concurrentDispatch 多個線程,並行執行
 */
void test_concurrentDispatch(){
    dispatch_queue_t myConcurrentDispatchQueue = dispatch_queue_create("com.example.gcd.MyConcurrentDispatchQueue", DISPATCH_QUEUE_CONCURRENT);
    void(^blk_0)(void) = ^() {
        NSLog(@"%s,%d",__func__,__LINE__);
    };
    void(^blk_1)(void) = ^() {
        NSLog(@"%s,%d",__func__,__LINE__);
    };
    void(^blk_2)(void) = ^() {
        NSLog(@"%s,%d",__func__,__LINE__);
    };
    void(^blk_3)(void) = ^() {
        NSLog(@"%s,%d",__func__,__LINE__);
    };
    void(^blk_4)(void) = ^() {
        NSLog(@"%s,%d",__func__,__LINE__);
    };
    void(^blk_5)(void) = ^() {
        NSLog(@"%s,%d",__func__,__LINE__);
    };
    void(^blk_6)(void) = ^() {
        NSLog(@"%s,%d",__func__,__LINE__);
    };
    void(^blk_7)(void) = ^() {
        NSLog(@"%s,%d",__func__,__LINE__);
    };
    dispatch_async(myConcurrentDispatchQueue, blk_0);
    dispatch_async(myConcurrentDispatchQueue, blk_1);
    dispatch_async(myConcurrentDispatchQueue, blk_2);
    dispatch_async(myConcurrentDispatchQueue, blk_3);
    dispatch_async(myConcurrentDispatchQueue, blk_4);
    dispatch_async(myConcurrentDispatchQueue, blk_5);
    dispatch_async(myConcurrentDispatchQueue, blk_6);
    dispatch_async(myConcurrentDispatchQueue, blk_7);
    //    dispatch_release(myConcurrentDispatchQueue);
    NSLog(@"%s,%d",__func__,__LINE__);
}
void test_Main_Global_DispatchQueue(){

    /**主線程*/
    dispatch_queue_t mainDispachQueue = dispatch_get_main_queue();
    /**高優先級*/
    dispatch_queue_t globalDispatchQueueHigh = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0);
    /**默認優先級*/
    dispatch_queue_t globalDisaptchQueueDefault = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
    /**低優先級*/
    dispatch_queue_t globalDispatchQueueLow = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_LOW, 0);
    /**後臺優先級*/
    dispatch_queue_t globalDispatchQueueBackground = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_BACKGROUND, 0);
}
/**改變線程的優先級*/
void test_dispatch_set_target_queue(){
    //要變更優先級的dispatch queue
    dispatch_queue_t myserialDispatchQueue = dispatch_queue_create("com.example.gcd.MySerialDispatchQueue", NULL);
    //目標
    dispatch_queue_t globalDispatchQueueBackground = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_BACKGROUND, 0);
    dispatch_set_target_queue(myserialDispatchQueue, globalDispatchQueueBackground);
}
void test_dispatch_after(){
    /*注意:
     dispatch_after函數並不是在指定時間後執行處理,
     而是在指定時間追加處理到Dispatch Queue
     NSEC_PER_SEC 秒
     NSEC_PER_MSEC 毫秒
     NSEC_PER_USEC 微妙
     */
    dispatch_time_t time = dispatch_time(DISPATCH_TIME_NOW, 3ull * NSEC_PER_USEC);
    dispatch_after(time, dispatch_get_main_queue(), ^{
        NSLog(@"%s %d",__func__,__LINE__);
    });
    NSDate *date = [[NSDate alloc]initWithTimeIntervalSinceNow:5];
    dispatch_after(getDispatchTimeByDate(date), dispatch_get_main_queue(), ^{
        NSLog(@"%s %d",__func__,__LINE__);
    });
    NSLog(@"%s %d",__func__,__LINE__);
}
//返回指定日期時間
dispatch_time_t getDispatchTimeByDate(NSDate *date){
    NSTimeInterval interval;
    double second, subsecond;
    struct timespec time;
    dispatch_time_t milestone;

    interval = [date timeIntervalSince1970];
    /*
     modf() 將浮點數分解爲整數和小數部分,其原型爲:
     double modf (double x, double* intpart);
     */
    subsecond = modf(interval, &second);

    time.tv_sec = second;
    time.tv_nsec = subsecond * NSEC_PER_SEC;

    milestone = dispatch_walltime(&time, 0);

    return milestone;
}

/**
 無論向什麼樣的Dispatch Queue中追加處理,使用Dispatch Group都可監視這些處理執行的結束.一旦測試到所有處理執行結束,就可將結束的處理追加到Dispatch Queue中
 */
void test_Dispatch_Group(){
    dispatch_queue_t queue = dispatch_queue_create(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
    dispatch_group_t group = dispatch_group_create();
    dispatch_async(queue, ^{
        NSLog(@"%s %d",__func__,__LINE__);
    });
    dispatch_async(queue, ^{
        NSLog(@"%s %d",__func__,__LINE__);
    });
    dispatch_async(queue, ^{
        NSLog(@"%s %d",__func__,__LINE__);
    });
//    notify(通知)
    dispatch_group_notify(group, dispatch_get_main_queue(), ^{
        NSLog(@"done");
    });

}
void test_Dispatch_group_wait(){
    dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
    dispatch_group_t group = dispatch_group_create();

    dispatch_group_async(group, queue, ^{
        NSLog(@"%s %d",__func__,__LINE__);
    });
    dispatch_group_async(group, queue, ^{
        NSLog(@"%s %d",__func__,__LINE__);
    });
    dispatch_group_async(group, queue, ^{
        sleep(4);
        NSLog(@"%s %d",__func__,__LINE__);
    });
    //在Dispatch Group中也可以使用dispatch_group_wait函數僅等待全部處理執行結束
//    dispatch_group_wait(group, DISPATCH_TIME_FOREVER);

    long result = dispatch_group_wait(group, dispatch_time(DISPATCH_TIME_NOW, 3ULL * NSEC_PER_SEC));
    if (result == 0) {
        NSLog(@"屬於Dispatch Group的全部處理執行結束");
    }else{
        NSLog(@"屬於Dispatch Group的某一個處理還在執行中");
    }
}

/**
 barrier(障礙)
 應用於處理數據的讀寫問題

 寫入處理不可以與其他的寫入處理以及包含讀取處理的其
 他某些處理並行執行.
 但是,讀取處理只是與讀取處理並行執行,那麼多個並行執
 行就不會發生問題.
 就是說:在寫入處理結束之前,讀取處理不可執行
 */
void test_dispatch_barrier_async(){
    dispatch_queue_t queue = dispatch_queue_create("com.example.gcd.ForBarrier", DISPATCH_QUEUE_CONCURRENT);
    dispatch_async(queue, ^{
        NSLog(@"reading data %d",__LINE__);
    });
    dispatch_async(queue, ^{
        NSLog(@"reading data %d",__LINE__);
    });
    dispatch_async(queue, ^{
        NSLog(@"reading data %d",__LINE__);
    });
    dispatch_async(queue, ^{
        NSLog(@"reading data %d",__LINE__);
    });
    dispatch_barrier_async(queue, ^{
        NSLog(@"begin writing data %d",__LINE__);
        sleep(4);
        NSLog(@"end writing data %d",__LINE__);

    });
//    dispatch_async(queue, ^{
//        NSLog(@"begin writing data %d",__LINE__);
//        sleep(4);
//        NSLog(@"end writing data %d",__LINE__);
//    });
    dispatch_async(queue, ^{
        NSLog(@"reading data %d",__LINE__);
    });
    dispatch_async(queue, ^{
        NSLog(@"reading data %d",__LINE__);
    });
}

/**
 asynchronous(異步的)
 synchronous(同步的)
 */
void test_dispatch_sync(){
//    dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
//    dispatch_sync(queue, ^{
//        NSLog(@"同步處理");
//    });

    //死鎖
//    dispatch_queue_t queue = dispatch_get_main_queue();
//    dispatch_sync(queue, ^{
//        NSLog(@"Hell world");
//    });
//    dispatch_async(queue, ^{
//        dispatch_sync(queue, ^{
//             NSLog(@"Hell world");
//        });
//    });
    dispatch_queue_t queue = dispatch_queue_create("com.example.gcd.MySerialDispatchQueue", NULL);
    dispatch_async(queue, ^{
        dispatch_sync(queue, ^{
            NSLog(@"Hell world");
        });
    });
}
void test_Dispatch_Apply(){
    dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
//    dispatch_apply(10, queue, ^(size_t index) {
//        NSLog(@"%zu",index);
//    });
    NSArray *array = @[@10, @9, @7, @6, @5, @4, @3, @2, @1];
    dispatch_async(queue, ^{
        dispatch_apply([array count], queue, ^(size_t index) {
            NSLog(@"%zu %@",index, [array objectAtIndex:index]);
        });
        dispatch_async(dispatch_get_main_queue(), ^{
            NSLog(@"done");
        });
    });
}

/**
 dispatch_supsend(queue)掛起
 dispatch_resume(queue)回覆
 */
void test_dispatch_supsend_dispatch_resume(){
    dispatch_queue_t queue = dispatch_queue_create("com.test.gcd", DISPATCH_QUEUE_SERIAL);
    //提交第一個block,延時5秒打印。
    dispatch_async(queue, ^{
        sleep(5);
        NSLog(@"After 5 seconds...");
    });
    //提交第二個block,也是延時5秒打印
    dispatch_async(queue, ^{
        sleep(5);
        NSLog(@"After 5 seconds again...");
    });
    //延時一秒
    NSLog(@"sleep 1 second...");
    sleep(1);
    //掛起隊列
    NSLog(@"suspend...");
    dispatch_suspend(queue);
    //延時10秒
    NSLog(@"sleep 10 second...");
    sleep(10);
    //恢復隊列
    NSLog(@"resume...");
//    dispatch_resume(queue);
}

/**
 semaphore(信號)
 */
void test_dispatch_semaphore(){
    dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);

    /**
     生成dispatch_semaphore.並將計數初始值設定爲1
     保持可訪問NSMutableArray類對象的線程同時只能有一個
     */
    dispatch_semaphore_t semaphore = dispatch_semaphore_create(1);

    NSMutableArray *array = [NSMutableArray array];

    for (int i = 0; i < 10000; i++) {
        //一直等待,直到Dispatch Semaphore 的計數值達到大於等於1
        dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER);
        [array addObject:[NSNumber numberWithInt:i]];
        /*

         */
        dispatch_semaphore_signal(semaphore);
    }
}

/**
 保證函數在應用程序中只執行一次處理
 生成單例對象使用
 */
void test_dispatch_once(){
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        NSLog(@"初始化單例");
    });
}
void test_dispatch_io(){
}
void test_timer(){
    NSLog(@"%s",__func__);
    /*指定DISPATCH_SOURCE_TYPE_TIMER, 作成Dispatch Source*/
    dispatch_source_t timer = dispatch_source_create(DISPATCH_SOURCE_TYPE_TIMER, 0, 0, dispatch_get_main_queue());
    /*
     將定時器設定爲15秒後
     不指定爲重複
     允許延遲1秒
     */
    dispatch_source_set_timer(timer, dispatch_time(DISPATCH_TIME_NOW, 15ULL * NSEC_PER_SEC), DISPATCH_TIME_FOREVER, 1ULL * NSEC_PER_SEC);
    //指定定時器時間內執行處理
    dispatch_source_set_event_handler(timer, ^{
        NSLog(@"wakeup");
        //取消Dispatch Source
        dispatch_source_cancel(timer);
    });
    //指定取消Dispatch Source時處理
    dispatch_source_set_cancel_handler(timer, ^{
        NSLog(@"cancel");
    });
    //啓動Dispatch Source
    dispatch_resume(timer);
}
 1. (void)countDownWithTime:(int)time
           countDownBlock:(void (^)(int timeLeft))countDownBlock
                 endBlock:(void (^)())endBlock
{
    __block int timeout = time; //倒計時時間
    dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
    dispatch_source_t _timer = dispatch_source_create(DISPATCH_SOURCE_TYPE_TIMER, 0, 0,queue);
    dispatch_source_set_timer(_timer,dispatch_walltime(NULL, 0),1.0*NSEC_PER_SEC, 0); //每秒執行
    dispatch_source_set_event_handler(_timer, ^{
        if(timeout<=0){ //倒計時結束,關閉
            dispatch_source_cancel(_timer);
            dispatch_async(dispatch_get_main_queue(), ^{
                if (endBlock) {
                    endBlock();
                }
            });
        } else {
            dispatch_async(dispatch_get_main_queue(), ^{
                timeout--;
                if (countDownBlock) {
                    countDownBlock(timeout);
                }
            });
        }
    });
    dispatch_resume(_timer);
}

2. NSThread

#pragma mark:NSThread
 1. (void)testThread{
    NSString *url = @"http://img4.imgtn.bdimg.com/it/u=2437762035,2994278153&fm=23&gp=0.jpg";
//    [NSThread detachNewThreadSelector:@selector(downLoadData:) toTarget:self withObject:url];
    NSThread *thread = [[NSThread alloc]initWithTarget:self selector:@selector(downLoadData:) object:url];
    [thread start];
}
 2. (void)downLoadData:(NSString *)url{
    NSLog(@"begin download.....");
    for (int i = 0 ; i < 5; i++) {
        sleep(1);
        NSLog(@"download....%d%%",(i+1) * 20);
    }
    NSLog(@"finish download......");
    [self performSelectorOnMainThread:@selector(refreshUI:) withObject:[NSData data] waitUntilDone:YES];
}
 3. (void)refreshUI:(NSData *)data{
    NSLog(@"%s",__func__);
}
 4. (void)test_tickets{
    tickets = 100;
    count = 0;
    theLock = [[NSLock alloc] init];
    // 鎖對象
    ticketsCondition = [[NSCondition alloc] init];
    ticketsThreadone = [[NSThread alloc] initWithTarget:self selector:@selector(run) object:nil];
    [ticketsThreadone setName:@"Thread-1"];
    [ticketsThreadone start];

    ticketsThreadtwo = [[NSThread alloc] initWithTarget:self selector:@selector(run) object:nil];
    [ticketsThreadtwo setName:@"Thread-2"];
    [ticketsThreadtwo start];
}
 5. (void)run{
    while (TRUE) {
        // 上鎖
        //        [ticketsCondition lock];
        [theLock lock];
        if(tickets >= 0){
            [NSThread sleepForTimeInterval:0.09];
            count = 100 - tickets;
            NSLog(@"當前票數是:%d,售出:%d,線程名:%@",tickets,count,[[NSThread currentThread] name]);
            tickets--;
        }else{
            break;
        }
        [theLock unlock];
        //        [ticketsCondition unlock];
    }   
}

3. NSOperation

/**
 使用 NSOperation的方式有兩種,
 一種是用定義好的兩個子類:NSInvocationOperation 和 NSBlockOperation。
 另一種是繼承NSOperation
 */
-(void)testNSOperation{
    NSString *url = @"http://img4.imgtn.bdimg.com/it/u=2437762035,2994278153&fm=23&gp=0.jpg";
    NSInvocationOperation *operation = [[NSInvocationOperation alloc]initWithTarget:self selector:@selector(downLoadData:) object:url];
    NSOperationQueue *queue = [[NSOperationQueue alloc]init];
    [queue addOperation:operation];
}

相關鏈接:http://blog.jobbole.com/69019/

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章