多線程編程——創建線程的三種方法

/**

 *  獲取網絡數據、處理大批量數據、使用到一些比較耗時的算法時,需要使用子線程處理

 */

1、創建子線程有三種方法
(1)、NSThread
(2)、NSOperationQueue
(3)、GCD

2、使用NSThread創建子線程

// 開啓一個子線程,把for循環交給子線程完成(每觸發一次就創建一個線程)

    NSThread *thread = [[NSThread allocinitWithTarget:self selector:@selector(cycle) object:nil];

    // 啓動子線程(手動啓動)

    [thread start];

    [thread release];

    

    // 啓動子線程,(自動啓動)

    [NSThread detachNewThreadSelector:@selector(cycle) toTarget:self withObject:nil];

    [NSThread detachNewThreadSelector:@selector(downloadImage) toTarget:self withObject:nil];

    // 自動啓動子線程 (等同上邊方法)

    [self performSelectorInBackground:@selector(downloadImage) withObject:nil];


3、使用NSOperationQueue創建子線程

// NSOperationQueue

    

    // 1.NSInvocationOperation

    NSInvocationOperation *invocationOperation = [[NSInvocationOperation allocinitWithTarget:self selector:@selector(test:) object:@"參數"];

   // [invocationOperation start];

   // [invocationOperation release];

    

    

    // 2.NSBlockOperation

    NSBlockOperation *blockOperation = [NSBlockOperation blockOperationWithBlock:^{

        NSLog(@"blockOperaction");

    }];

   // [blockOperation start];

    

    

    // 3.NSOperationQueue(用來存放任務的隊列)

    NSOperationQueue *queue = [[NSOperationQueue allocinit];

    // 添加依賴關係,當一個任務執行完後,另一個再執行(設置當block執行完成後再執行invocationoperation

    [invocationOperation addDependency:blockOperation];

    // 設置最大可同時執行的任務數量

    // queue.maxConcurrentOperationCount = 1;

    //  添加任務到隊列中(將任務添加到隊列中後會自動執行,不必手動start)

    [queue addOperation:invocationOperation];

    [queue addOperation:blockOperation];

    [invocationOperation release];



4、使用GCD創建子線程

 /**

     *  1.GCD 分派隊列 FIFO

     *  2.串行隊列:前一個任務執行完畢,下一個任務纔開始執行

     *  3.並行隊列:任務在派發的過程中是有序的,但是不用等待前一個任務完成,下一個任務就可以開始

     *  4.GCD中的隊列分爲三種,主隊列,全局隊列,自定義隊列

     */

    

    

    

    // 1.使用主隊列實現任務的派發,串行。主隊列分派的任務,永遠在主線程中

    dispatch_queue_t mainQueue = dispatch_get_main_queue();

    // 1.1 添加任務

    dispatch_async(mainQueue, ^{

        NSLog(@"第一個任務,當前線程是:%@",[NSThread currentThread]);

    });

    dispatch_async(mainQueue, ^{

        NSLog(@"第二個任務,當前線程是:%@",[NSThread currentThread]);

    });

    dispatch_async(mainQueue, ^{

        NSLog(@"第三個任務,當前線程是:%@",[NSThread currentThread]);

    });

    dispatch_async(mainQueue, ^{

        NSLog(@"第四個任務,當前線程是:%@",[NSThread currentThread]);

    });


// 2.自己創建隊列,串行,任務會分派在子線程中

    dispatch_queue_t myQueue = dispatch_queue_create("com.lanou.myqueue"DISPATCH_QUEUE_SERIAL);//DISPATCH_QUEUE_SERIAL:串行

    // 2.1添加任務

    dispatch_async(myQueue, ^{

        NSLog(@"第一個任務,當前線程是:%@",[NSThread currentThread]);

    });

    dispatch_async(myQueue, ^{

        NSLog(@"第二個任務,當前線程是:%@",[NSThread currentThread]);

    });

    dispatch_async(myQueue, ^{

        NSLog(@"第三個任務,當前線程是:%@",[NSThread currentThread]);

    });

    dispatch_async(myQueue, ^{

        NSLog(@"第四個任務,當前線程是:%@",[NSThread currentThread]);

    });


    // 3.自定義隊列,並行

    dispatch_queue_t myQueue = dispatch_queue_create("com.lanou.myQueue"DISPATCH_QUEUE_CONCURRENT);//DISPATCH_QUEUE_CONCURRENT:並行

    dispatch_async(myQueue, ^{

        NSLog(@"第一個任務,當前線程是:%@",[NSThread currentThread]);

    });

    dispatch_async(myQueue, ^{

        NSLog(@"第二個任務,當前線程是:%@",[NSThread currentThread]);

    });

    dispatch_async(myQueue, ^{

        NSLog(@"第三個任務,當前線程是:%@",[NSThread currentThread]);

    });

    dispatch_async(myQueue, ^{

        NSLog(@"第四個任務,當前線程是:%@",[NSThread currentThread]);

    });



    // 4.利用系統創建並行隊列

    dispatch_queue_t queue2 = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT0);//DISPATCH_QUEUE_PRIORITY_DEFAULT 優先級默認

    dispatch_async(queue2, ^{

        NSLog(@"第一個任務,當前線程是:%@",[NSThread currentThread]);

    });

    dispatch_async(queue2, ^{

        NSLog(@"第二個任務,當前線程是:%@",[NSThread currentThread]);

    });

    dispatch_async(queue2, ^{

        NSLog(@"第三個任務,當前線程是:%@",[NSThread currentThread]);

    });

    dispatch_async(queue2, ^{

        NSLog(@"第四個任務,當前線程是:%@",[NSThread currentThread]);

    });





 // 5.實例:獲取網絡圖片數據

    

    __block ViewController *vc = self;

    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT0), ^{

        // 5.1 獲取網絡圖片數據

        NSURL *url = [NSURL URLWithString:@"http://pic1.win4000.com/wallpaper/6/53bfb7f60d991.jpg"];

        NSData *data = [NSData dataWithContentsOfURL:url];

        UIImage *image = [UIImage imageWithData:data];

        

        // 5.2在主線程中顯示圖片數據

        dispatch_async(dispatch_get_main_queue(), ^{

            [vc showImage:image];

        });

    });






    /**

     *  GCD提供的福利

     */

    

    for (int i = 0; i < 10; i++) {

        static dispatch_once_t onceToken; //讓代碼只走一次dispatch_once_GCD.....

        dispatch_once(&onceToken, ^{

            NSLog(@"haha");

        });

    }

    

    for (int i = 0; i < 10; i++) {  // 代碼延遲五秒執行:dispatch_after_GCD......

        dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(5 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{

            NSLog(@"讓代碼延遲五秒執行");

        });

    }

    

    // 指定代碼執行若干次

    dispatch_apply(4dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT0), ^(size_t t) {

        NSLog(@"指定代碼執行若干次");

    });

    

    /**

     *  1.脫離線程:當線程內部代碼執行完畢後,線程自動關閉,稱爲脫離線程。例如:NSThread,Background

     *  2.非脫離線程:當線程內部代碼執行完畢後,線程不關閉,等待着繼續被使用,稱爲非脫離線程。例如:NSOperation

     */


5、從子線程切換到主線程的兩種方法
方法一:

// 5.2在主線程中顯示圖片數據

        dispatch_async(dispatch_get_main_queue(), ^{

            [vc showImage:image];

        });

方法二:

// 5.回到主線程顯示圖片

        

        [self performSelectorOnMainThread:@selector(showImage:) withObject:image waitUntilDone:YES];

發佈了69 篇原創文章 · 獲贊 8 · 訪問量 8萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章