iOS-Senior10-多線程(子線程建立)

1.多線程概述編程

程序:由源代碼生成的可執行應用。(eg:QQ.app)網絡

進程:一個正在運行的程序能夠看作一個進程。(eg:正在運行的QQ就是一個進程),進程用用獨立運行所需的所有資源。
session

線程:程序中獨立運行的代碼段。(eg:接收QQ消息的代碼)多線程

一個進程是由一或多個線程組成。進程只負責資源的調度和分配,線程纔是程序真正的執行單元,負責代碼的執行。併發

1.1單線程app

每一個正在運行的程序(即進程),至少包含一個線程,這個線程就叫主線程async

主線程在程序啓動時被建立,用於執行main函數。函數

只有一個主線程的程序,稱爲單線程程序。性能

在單線程程序中,主線程負責執行程序的全部代碼(UI展示以及刷新,網絡請求,本地存儲等等)。這些代碼只能順序執行,沒法併發執行。優化

1.2多線程

擁有多個線程的程序,稱做多線程程序。

iOS中容許用戶本身開闢新的線程,相對於主線程來說,這些線程,稱做子線程。

能夠根據須要開闢若干子線程。

子線程和主線程都是獨立的運行單元,各自執行互不影響,所以可以併發執行。

1.3單線程和多線程的區別

單線程程序:只有一個線程,即主線程,代碼順序執行,容易出現代碼阻塞(頁面假死)。

多線程程序:有多個線程,線程間獨立運行,能有效的避免代碼阻塞,而且提升程序的運行性能。

注意:iOS中關於UI的添加和刷新必須在主線程中操做。

2.iOS平臺下的多線程

2.1NSThread

方法:

//初始化一個子線程,但須要手動開啓

- (id) initWithTarget : (id) target selector : (SEL)selector object :(id)argument

//初始化一個子線程,並自動開啓

+ (void) detachNewThreadSelector : (SEL) aSelector toTarget : (id) aTarget withObject :(id) anArgument

//開啓子線程

start   [operation start]

//取消當前子線程

cancel [operation cancel]

源代碼:

//手動開闢子線程

NSThread *thread = [[NSThread alloc] initWithTarget : self selector:@selector(sayHi) object:nil];

[thread start];

//使用NSThread和NSObject實現的開闢線程,系統會自動釋放,關不關都行

[thread cancel]; 沒有真正取消,而是給線程發送一個信號,經過這個信號進行取消的

[thread exit];  直接將線程退出

//自動開啓子線程

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

self.view.backgroundColor = [UIColor redColor] ;

2.2NSObject

//使用performSelectorInBackground開闢子線程

[self performSelectorInBackground :@selector(sayHi) withObject:@"test"];

//在子線程調用的方法裏返回主線程,在調用另外一個方法

[self performSelectoraOnMainThread:@selector(mainThreadChangeColor) withObject :nil waitUntilDone: YES];

- (void)mainThreadChangeColor {

self.view.backgroudColor = [UIColor magentaColor];

}

方法:

獲取當前線程:[NSThread currentThread]

獲取主線程   :[NSThread mainThread]

線程休眠2秒 :[NSThread sleepForTimeInterval:2]

注意:

1.每一個線程都維護這與本身對應的NSAutoreleasePool對象,將其放在線程棧的棧頂。當線程結束時,會清空自動釋放池。

2.爲保證對象的及時釋放,在多線程方法中須要添加自動釋放池。

3.在應用程序打開的時候,系統會自動爲主線程建立一個自動釋放池。

4.咱們手動建立的子線程須要咱們手動添加自動釋放池。

4.NSOperation和NSOperationQueue

NSOperation類,在NVC中屬於M,是用來封裝單個任務相關的代碼和數據的抽象類。

由於它是抽象的,不可以直接使用這個類,而是使用子類(NSInvocation,NSBlockOperation)來執行實際任務。

NSOperation(含子類),只是一個操做,自己無主線程,子線程之分,可在任意線程中使用。一般與NSOperationQueue結合使用。

//NSInvocationOperation:封裝了執行操做的target和要執行的action

 

//NSBlockOperation:封裝了須要執行的代碼

//NSOperation不能直接進行多線程的建立,須要藉助:NSOperationQueue

//在單獨使用NSOperation的子類去建立線程的時候,必定要啓動才行;

//在使用NSOperation的子類去建立線程的時候,實際上線程沒有真正意義上的建立

源程序:

NSInvocationOperation *operation = [[NSInvocationOperation alloc]initWithTarget:self selector:@selector(test) object:nil];

 

NSBlockOperation *blockOperation = [NSBlockOperation blockOperationWithBlock:^{

        NSLog(@"我是block");

        NSLog(@"+++++%@",[NSThread currentThread]);

        NSLog(@"*******%@",[NSThread mainThread]);

    }];

- (void)test {

    NSLog(@"☺");

    NSLog(@"currentThread == %@",[NSThread currentThread]);

    NSLog(@"mainThread ==  %@",[NSThread mainThread]);

}

    //藉助隊列,建立子線程

    NSOperationQueue *queue = [[NSOperationQueue alloc] init];

    [queue addOperation:operation];

    [queue addOperation:blockOperation]; //有addOperation的時候,就不能夠用start,不然會形成崩潰

 

- (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event {

    //建立隊列的對象

    NSOperationQueue *queue = [[NSOperationQueue alloc] init];

    //最大的併發數量值

    //當值設置爲1的時候,能夠叫作串行(單線程)順序執行

    queue.maxConcurrentOperationCount = 2;

    //當值設置大於1的時候,叫作並行:多條通道同時進行各自的任務

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

        //建立10個線程

        NSBlockOperation *blockOperation = [NSBlockOperation blockOperationWithBlock:^{

            NSLog(@"currentThread == %@,mainThread == %@,%d",[NSThread currentThread],[NSThread mainThread],i);

         }];

        [queue addOperation:blockOperation];

 }

 }

5.GCD(Grand Central Dispatch)使用

簡介:GCD是Apple開發的一種多核編程技術。主要用於優化應用程序以支持多核處理器以及其餘對稱多處理系統。

GCD提供函數實現多線程開發,性能更高,功能也更強大。

它首次發佈在Mac OS X 10.6,iOS4及以上也能夠用。

任務:具備必定功能的代碼段。通常是一個block或者函數。

分發隊列:GCD以隊列的方式進行工做,FIFO(先進先出)

GCD會根據分發隊列的類型,建立合適數量的線程執行隊列中的任務。

GCD中兩種隊列:

1.SerialQueue:一次只執行一個任務。Serial queue一般用於一般用於同步訪問特定的資源或數據。當你建立多個Serial queue時,雖然他們各自是同步執行的,但Serial queue與Serial queue之間是併發執行的。

2.Concurrent:能夠併發地執行多個任務,可是遵照FIFO

#pragma mark - 使用GCD去建立一個串行隊列

//第一種:系統提供的建立串行隊列的方法

dispatch_queue_t queue = dispatch_get_main_queue();

//在真正的開發中若是須要建立串行隊列,比較習慣用這種

//第二種:本身去建立

dispatch_queue_t = dispatch_queue_create(DISPATCH_QUEUE_SERIAL,0);

#pragma mark - 使用GCD去建立並行隊列

//第一種:系統的方式

//參數1:優先級(有4個,沒有明顯的區別)

dispatch_queue_t queue = dispatch_get_globel_queue(DISPATCH_QUEUE_PRIORITY);

//第二種:本身定義的方式(參數和串行不同)

//參數1:表示建立隊列的名字

//參數2:系統提供的宏

//建立隊列

dispatch_queue_t queue = dispatch_queue_create("myQueue",DISPATCH_QUEUE_CONCURRENT);

//建立任務

dispatch_async(queue,^{

NSLog(@"current == %@",[NSThread currentThread]);

NSLog(@"main == %@",[NSThread MainThread]);

NSLog(@"我是任務一,子進程一");

});

 

dispatch_async(queue,^{

NSLog(@"current == %@",[NSThread currentThread]);

NSLog(@"main == %@",[NSThread MainThread]);

NSLog(@"我是任務二,子進程二");

});

 

dispatch_async(queue,^{

NSLog(@"current == %@",[NSThread currentThread]);

NSLog(@"main == %@",[NSThread MainThread]);

NSLog(@"我是任務三,子進程三");

});

 

#pragma mark - 幾秒以後去作每一件事

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

NSLog(@"3.0秒的時候");

}

);

#pragma mark - 重複向一個隊列中添加多個任務

dispatch_queue_t queue = dispatch_queue_create(0,DISPATH_QUEUE_CONCURRENT);

dispatch_apply(100,queue,^(size_t index)) {

NSLog(@"index = %zu",index);

}

#pragma mark - 分組

//建立一個分組

dispatch_group_t group = dispatch_group_create();

//建立一個並行隊列

dispatch_queue_t queue = dispatch_queue_create(0,DISPATCH_QUEUE_CONCURRENT);

//建立任務1

dispatch_group_asunc(group,queue,^{

NSLog(@"我是任務1");

});

//建立任務2

dispatch_group_asunc(group,queue,^{

NSLog(@"我是任務2");

});

//建立任務3

dispatch_group_asunc(group,queue,^{

NSLog(@"我是任務3");

});

//用於監聽全部任務的執行狀況的,因此此功能代碼必須放在全部任務以後進行書寫的

dispatch_group_notify(group,queue,^{

NSLog(@"我是監聽的,最後執行");

});

#pragma mark - 併發中的串行(披着羊皮的狼)

//建立的串行隊列

dispatch_queue_t queue = dispatch_queue_create(0,DISPATH_QUEUE_CONCURRENT);

 

dispatch_async(queue,^{

NSLog(@"任務1");

});

 

dispatch_async(queue,^{

 

NSLog(@"任務2");

 

});

 

dispatch_async(queue,^{

NSLog(@"任務3");

});

 

#pragma mark - loadData

//1.url

NSURL *url = [NSURL URLWithString:@"http://www.baidu.com"];

//2.session

NSURLSession *session = [NSURLSession sharedSession];

//3.task

NSURLSessionDataTask *task = [session dataTaskWithURL:url completionHandler:^(NSData *_NUllabel data,NSURLResponse *_Nullabel response,NSError *_Nullable error){

if(error == nil){

//處理數據

//回到主線程刷新UI

dispatch_async(dispatch_get_main_queue(),^{

//本身靈活的寫點東西吧!!!

})

}

}];

相關文章
相關標籤/搜索