1.多線程-NSThread

1.在主線程執行屢次NSLog模擬耗時操做網絡

結果,卡住主線程異步

解決方案: performSelectorInBackground讓程序在後臺執行
 
2.pthread的使用
開闢子線程,執行一個函數
__bridge橋接,OC對象和C指針之間的轉換
{  /*
        參數1:線程的編號(地址)
        參數2:線程的屬性 NULL nil(oc)
        參數3:要調用的函數 void *  (*)  (void *)
        參數4:給要調用的函數傳遞的參數
     */
    //開闢新的線程
    pthread_t ID;
    NSString *str = @"ls";
    //__bridge橋接 類型轉換(oc - 》c)
    //MRC 誰建立,誰釋放
    //ARC 自動管理
    int result = pthread_create(&ID, NULL, demo, (__bridge void *)(str));
    //result 0 表明成功 其餘表明失敗
    if (result == 0) {
        NSLog(@"成功");
    }else
    {
        NSLog(@"失敗");
    }
    
}
/**
    pthread調用的函數
 */
void * demo(void * param)
{
    NSString *Str = (__bridge NSString *)(param);
    //獲取當前的代碼執行在哪一個線程當中,獲取當前線程
    NSLog(@"%@ %@",Str,[NSThread currentThread]);
    return NULL;
}

3.NSThread的3種使用方式函數

{   //建立
    NSThread *thread = [[NSThread alloc]initWithTarget:self selector:@selector(demo) object:nil];
    //調用
    [thread start];
    
//    //方式2
    [NSThread detachNewThreadSelector:@selector(demo) toTarget:self withObject:nil];
    
    //方式3
    [self performSelectorInBackground:@selector(demo) withObject:nil];
    
    //傳遞參數
    [self performSelectorInBackground:@selector(demo2:) withObject:@"HM"];
    
}
- (void)demo2:(NSString *)str
{
    NSLog(@"%@ %@",str,[NSThread currentThread]);
}
/**
    要調用的方法
 */
- (void)demo
{
    NSLog(@"%@",[NSThread currentThread]);
}

4.線程的生命週期ui

- (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event
{
    //新建狀態
    NSThread *thread = [[NSThread alloc]initWithTarget:self selector:@selector(demo) object:nil];
    //就緒狀態
    [thread start];
    
    //運行狀態:系統控制的
    
    
}
- (void)demo
{
    for (int i = 0; i <20; i++) {
        
        if (i == 5) {
            //阻塞狀態
            //讓當前的線程睡一段時間
            [NSThread sleepForTimeInterval:3];
        }else if (i == 10)
        {
            //死亡狀態
            [NSThread exit];
        }
        NSLog(@"%d",i);
    }
}

5.NSThread的屬性,能夠設置屬性的名稱、優先級atom

- (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event
{
    //線程屬性
    //主線程佔用的內存空間
    NSLog(@"%zd",[NSThread currentThread].stackSize/1024);
    //建立線程1
    NSThread *thread = [[NSThread alloc]initWithTarget:self selector:@selector(demo) object:nil];
    //設置線程名稱
    thread.name = @"t1";
    //設置線程的優先級 參數的取值範圍 0-1  0是優先級最低的,1是優先級最高 默認的是0.5
    [thread setThreadPriority:1.0];
    [thread start];
    
    //建立線程2
    NSThread *thread2 = [[NSThread alloc]initWithTarget:self selector:@selector(demo) object:nil];
    //設置線程名稱
    thread2.name = @"t2";
    [thread2 setThreadPriority:0.0];
    [thread2 start];
    
    //設置線程的優先級不能絕對保證線程優先執行,可是線程被調用的機率提升
    
}
- (void)demo
{
    
    //子線程佔用的內存空間
    NSLog(@"demo  %zd",[NSThread currentThread].stackSize/1024);
//    NSLog(@"%@",[NSThread currentThread]);
    for (int i = 0; i < 10; i++) {
        NSLog(@"%d %@",i,[NSThread currentThread].name);
        
    }
    
}

6.線程間資源搶奪的時候,須要加互斥鎖(鎖住一個對象)url

#import "ViewController.h"

@interface ViewController ()
//總票數
@property(nonatomic,assign)int totalTickets;
@end

@implementation ViewController

- (void)viewDidLoad {
    [super viewDidLoad];
    //設置票數爲20
    self.totalTickets = 20;
    
}
- (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event
{
    //窗口1 模擬賣票
    NSThread *thread = [[NSThread alloc]initWithTarget:self selector:@selector(sellTickets) object:nil];
    thread.name = @"t1";
    [thread start];
    
    
    //窗口2 模擬賣票
    
    NSThread *thread2 = [[NSThread alloc]initWithTarget:self selector:@selector(sellTickets) object:nil];
    thread2.name = @"t2";
    [thread2 start];
}
/**
    賣票
 */
- (void)sellTickets
{
    while (YES) {
        //被加鎖的對象
        @synchronized(self) {
            //查詢剩餘的票數,判斷
            if (self.totalTickets > 0) {
                self.totalTickets = self.totalTickets - 1;
                NSLog(@"剩餘%d票 %@",self.totalTickets,[NSThread currentThread].name);
            }else
            {
                NSLog(@"票賣完了,回不了家,走路回家");
                break;
            }
        }
       
    }
}

7.異步下載圖片,在子線程下載圖片,在主線程更新UIspa

- (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event
{
    //網絡圖片下載
    /*
            1.不能把耗時操做放到主線程中,開闢新的線程
            2.刷新ui必定要在主線程
//     http://g.hiphotos.baidu.com/image/pic/item/f31fbe096b63f624cd2991e98344ebf81b4ca3e0.jpg
     */
    NSThread *thread = [[NSThread alloc]initWithTarget:self selector:@selector(downloadImg) object:nil];
    [thread start];
    
    
}
/**
    下載圖片
 */
- (void)downloadImg
{
    NSLog(@"downloadImg %@",[NSThread currentThread]);
    //獲取連接地址
    NSURL *url = [NSURL URLWithString:@"http://g.hiphotos.baidu.com/image/pic/item/f31fbe096b63f624cd2991e98344ebf81b4ca3e0.jpg"];
    //轉化NSData類型
    NSData *data = [NSData dataWithContentsOfURL:url];
    //轉化成UIImage
    UIImage *img = [UIImage imageWithData:data];
    
    /*
        參數1:主線程要調用的方法
        參數2:給調用的方法傳遞的參數
        參數3:是否等待當前代碼執行完畢再來執行下面的代碼
     */
    [self performSelectorOnMainThread:@selector(updataUI:) withObject:img waitUntilDone:YES];
    NSLog(@"end");
    
}
/**
    刷新ui ui刷新必須放到主線程裏面
 */
- (void)updataUI:(UIImage *)img
{
    NSLog(@"updataUI %@",[NSThread currentThread]);
    [NSThread sleepForTimeInterval:3];
    self.HMImageView.image = img;
}
相關文章
相關標籤/搜索