国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁 > 學院 > 開發設計 > 正文

iOS多線程01

2019-11-14 18:20:38
字體:
來源:轉載
供稿:網友
  • 進程

    • 進程是指在系統中正在運行的一個應用程序
  • 線程

    • 1個進程要想執行任務,必須得有線程(每1個進程至少要有1條線程)
    • 1個線程中任務的執行是串行的(執行完上一個才能執行下一個)
  • 多線程

    • 1個進程中可以開啟多條線程,多條線程可以并行(同時)執行不同的任務
    • 線程可以并行, 但是每個線程中的任務還是串行
  • 多線程原理

    • 多線程并發(同時)執行,其實是CPU快速地在多條線程之間調度(切換)
  • 多線程優缺點

    • 優點
      • 能適當提高程序的執行效率
      • 能適當提高資源利用率(CPU、內存利用率)
    • 缺點
      • 線程越多,CPU在調度線程上的開銷就越大
      • 如果開啟大量的線程,會降低程序的性能
      • 程序設計更加復雜:比如線程之間的通信、多線程的數據共享

  • pthread
    • 類型: C語言中類型的結尾通常 _t/Ref,而且不需要使用 *
    • /*參數:1. 線程代號的地址2. 線程的屬性3. 調用函數的指針  - void *(*)(void *)  - 返回值 (函數指針)(參數)  - void * 和 OC 中的 id 是等價的4. 傳遞給該函數的參數返回值:如果是0,表示正確如果是非0,表示錯誤碼*/NSString *str = @"jx";pthread_t thid;int res = pthread_create(&thid, NULL, &demo, (__bridge void *)(str));if (res == 0) {  NSLog(@"OK");} else {  NSLog(@"error %d", res);}
  • NSThread

    • 一個NSThread對象就代表一條線程
  • 創建線程的幾種方式

  • // 1.創建線程 NJThread *thread = [[NJThread alloc] initWithTarget:self selector:@selector(demo:) object:@"jx"]; // 設置線程名稱 [thread setName:@"ljx"]; // 設置線程的優先級 // 優先級僅僅說明被CPU調用的可能性更大   [thread setThreadPRiority:1.0]; // 2.啟動線程 [thread start];
    - detach/performSelector    + 優點:簡單快捷    + 缺點:無法對線程進行更詳細的設置```objc// 1.創建線程[NSThread detachNewThreadSelector:@selector(demo:) toTarget:self withObject:@"jx"];// 1.創建線程// 注意: Swift中不能使用, 蘋果認為這個方法不安全    [self performSelectorInBackground:@selector(demo:) withObject:@"jx"];
  • 線程狀態
  •     啟動線程    NSThread *thread = [[NSThread alloc] initWithTarget:self selector:@selector(run) object:nil];[thread start];    // 進入就緒狀態 ->         運行狀態。當線程任務執行完畢,自動進入死亡狀態    阻塞(暫停)線程    + (void)sleepUntilDate:(NSDate *)date;    + (void)sleepForTimeInterval:(NSTimeInterval)ti;    // 進入阻塞狀態    強制停止線程    + (void)exit;    // 進入死亡狀態注意:一旦線程停止(死亡)了,就不能再次開啟任務   如圖:

    多線程的安全隱患

    • 被鎖定的代碼同一時刻只能有一個線程執行
    • @synchronized(鎖對象) { // 需要鎖定的代碼  }
  • 互斥鎖的優缺點 優點:能有效防止因多線程搶奪資源造成的數據安全問題 缺點:需要消耗大量的CPU資源

  • 互斥鎖注意點

    • 鎖定1份代碼只用1把鎖,用多把鎖是無效的
    • 鎖定范圍越大, 性能越差

  • 原子和非原子屬性

    • atomic:線程安全,需要消耗大量的資源
    • nonatomic:非線程安全,適合內存小的移動設備
  • 自旋鎖 & 互斥鎖

    • 共同點 都能夠保證同一時間,只有一條線程執行鎖定范圍的代碼
    • 不同點
      • 互斥鎖:如果發現有其他線程正在執行鎖定的代碼,線程會進入"休眠"狀態,等待其他線程執行完畢,打開鎖之后,線程會被"喚醒"
      • 自旋鎖:如果發現有其他線程正在執行鎖定的代碼,線程會"一直等待"鎖定代碼執行完成! 自旋鎖更適合執行非常短的代碼!

  • 線程間通信
      • 子線程做耗時操作, 主線程更新數據
  • #import "ViewController.h"@interface ViewController ()@property (weak, nonatomic) IBOutlet UIImageView *imageView;@end@implementation ViewController- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event{        // 開啟一個子線程下載圖片    [self performSelectorInBackground:@selector(downlod) withObject:nil];}- (void)downlod{    NSLog(@"%@", [NSThread currentThread]);    // 1.下載圖片     NSURL *url = [NSURL URLWithString:@"http://pic.4j4j.cn/upload/pic/20130531/07ed5ea485.jpg"];     NSData *data = [NSData dataWithContentsOfURL:url];    // 2.將二進制轉換為圖片    UIImage *image = [UIImage imageWithData:data];        // 3.跟新UI#warning 注意: 千萬不要在子線程中更新UI, 會出問題        /*     waitUntilDone:      YES: 如果傳入YES, 那么會等待updateImage方法執行完畢, 才會繼續執行后面的代碼     NO:  如果傳入NO, 那么不會等待updateImage方法執行完畢, 就可以繼續之后后面的代碼     */    /*    [self performSelectorOnMainThread:@selector(updateImage:) withObject:image waitUntilDone:NO];     */        // 開發中常用//    [self.imageView performSelectorOnMainThread:@selector(setImage:) withObject:image waitUntilDone:YES];        // 可以在指定的線程中, 調用指定對象的指定方法    [self performSelector:@selector(updateImage:) onThread:[NSThread mainThread] withObject:image waitUntilDone:YES];    }- (void)updateImage:(UIImage *)image{    NSLog(@"%@", [NSThread currentThread]);    // 3.更新UI    self.imageView.image = image;    }
  • GCD
  • GCD中有2個核心概念

    • 任務:執行什么操作
    • 隊列:用來存放任務
  • 執行任務

    • 同步方法: dispatch_sync
    • 異步方法: dispatch_async
    • 同步和異步的區別
      • 同步:只能在當前線程中執行任務,不具備開啟新線程的能力
      • 異步:可以在新的線程中執行任務,具備開啟新線程的能力
  • 隊列

    • 并發隊列
      • 可以讓多個任務并發(同時)執行(自動開啟多個線程同時執行任務)
      • 并發功能只有在異步(dispatch_async)函數下才有效
      • GCD默認已經提供了全局的并發隊列,供整個應用使用,可以無需手動創建            使用dispatch_get_global_queue函數獲得全局的并發隊列            dispatch_queue_t dispatch_get_global_queue(            dispatch_queue_priority_t priority, //                    隊列的優先級            unsigned long flags); // 此參數暫時無用,用0即可            獲得全局并發隊列            dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);            全局并發隊列的優先級            #define DISPATCH_QUEUE_PRIORITY_HIGH 2 //            #define DISPATCH_QUEUE_PRIORITY_DEFAULT 0 // 默認(中)            #define DISPATCH_QUEUE_PRIORITY_LOW (-2) //            #define DISPATCH_QUEUE_PRIORITY_BACKGROUND INT16_MIN // 后臺

         

    • 串行隊列    * 讓任務一個接著一個地執行(一個任務執行完畢后,再執行下一個任務)
    •         GCD中獲得串行有2種途徑        使用dispatch_queue_create函數創建串行隊列        // 創建串行隊列(隊列類型傳遞NULL或者DISPATCH_QUEUE_SERIAL)        dispatch_queue_t queue = dispatch_queue_create("com.520it.queue", NULL);        使用主隊列(跟主線程相關聯的隊列)        主隊列是GCD自帶的一種特殊的串行隊列        放在主隊列中的任務,都會放到主線程中執行        使用dispatch_get_main_queue()獲得主隊列        dispatch_queue_t queue = dispatch_get_main_queue();
    • 注意點

      同步和異步主要影響:能不能開啟新的線程
      • 同步:只是在當前線程中執行任務,不具備開啟新線程的能力
      • 異步:可以在新的線程中執行任務,具備開啟新線程的能力
      并發和串行主要影響:任務的執行方式
      • 并發:允許多個任務并發(同時)執行
      • 串行:一個任務執行完畢后,再執行下一個任務
    • 各種任務隊列搭配

      • 同步 + 串行 *
      • 同步 + 并發 *
      • 異步 + 串行 *
      • 異步 + 并發 *
      • 異步 + 主隊列 *
      • 同步 + 主隊列 *
    • GCD線程間通信

    • dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{    // 執行耗時的異步操作...      dispatch_async(dispatch_get_main_queue(), ^{        // 回到主線程,執行UI刷新操作        });});
    • GCD其它用法
    • 延時執行
    • dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(2.0 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{    // 2秒后執行這里的代碼...});

       

    • 一次性代碼

      • 使用dispatch_once函數能保證某段代碼在程序運行過程中只被執行1次
    • static dispatch_once_t onceToken; dispatch_once(&onceToken, ^{ // 只執行1次的代碼(這里面默認是線程安全的) });

       

    • 快速迭代
    • dispatch_apply(10, dispatch_get_global_queue(0, 0), ^(size_t index){    // 執行10次代碼,index順序不確定});
    • barrier
      • 在前面的任務執行結束后它才執行,而且它后面的任務等它執行完成之后才會執行
      • 不能是全局的并發隊列
      • 所有的任務都必須在一個隊列中
      • dispatch_barrier_async(dispatch_queue_t queue, dispatch_block_t block);
    • 隊列組
    • dispatch_group_t group =  dispatch_group_create();dispatch_group_async(group, dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{    // 執行1個耗時的異步操作});dispatch_group_async(group, dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{    // 執行1個耗時的異步操作});dispatch_group_notify(group, dispatch_get_main_queue(), ^{    // 等前面的異步操作都執行完畢后,回到主線程...});
    • iOS中多線程的實現方案

      • 如圖:
    • 單例模式

      • 單例模式的作用

        - 可以保證在程序運行過程,一個類只有一個實例,而且該實例易于供外界訪問,從而方便地控制了實例個數,并節約系統資源
      • 單例模式的使用場合

        • 在整個應用程序中,共享一份資源(這份資源只需要創建初始化1次)
      • ARC中,單例模式的實現

      • 在.m中保留一個全局的static的實例        static id _instance;        重寫allocWithZone:方法,在這里創建唯一的實例(注意線程安全)        + (instancetype)allocWithZone:(struct _NSZone *)zone        {            static dispatch_once_t onceToken;            dispatch_once(&onceToken,^{            _instance = [super allocWithZone:zone];            });             return _instance;        }        提供1個類方法讓外界訪問唯一的實例        + (instancetype)sharedInstance        {            static dispatch_once_t onceToken;            dispatch_once(&onceToken, ^{            _instance = [[self alloc] init];             });            return _instance;        }        實現copyWithZone:方法        - (id)copyWithZone:(struct _NSZone *)zone        {            return _instance;        }        注意點            // 注意點: 單例是不可以繼承的, 如果繼承引發問題            // 如果先創建父類, 那么永遠都是父類            // 如果先創建子類, 那么永遠都是子類

         


發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
主站蜘蛛池模板: 齐河县| 民勤县| 东兰县| 东阿县| 繁峙县| 德保县| 宕昌县| 五原县| 蓬安县| 冀州市| 花莲县| 龙南县| 泽普县| 务川| 汶上县| 莱西市| 金山区| 社旗县| 临江市| 合水县| 兰考县| 泽州县| 武义县| 营山县| 奇台县| 陈巴尔虎旗| 乐亭县| 兴化市| 上饶县| 枣阳市| 阜新| 石柱| 盐津县| 南宁市| 平和县| 黔西县| 宁晋县| 崇文区| 平湖市| 宝应县| 建阳市|