UI進階——多線程

一、多線程的概念

線程就是指每個獨立運行的代碼片;
每個賑災運行的程序(即進程),至少包含一個線程,這個線程爲主線程。
只有一個主線程的程序,稱爲單線程程序。
擁有多個線程的程序,稱爲多線程程序。
多個線程可以併發執行。
注意:
iOS中關於UI的添加和刷新必須在主線程中操作。

iOS中多線程的種類有四種:
NSThread
NSOperationQueue(是隊列,沒有開闢線程的能力)
NSObject
GCD

二、NSThread

demo:

-(void)tesr{
    UIImageView* imageView = [[UIImageView alloc]initWithImage:[UIImage imageNamed:@"1.jpg"]];
    [self.view addSubview:imageView];
    
    
    //輕量級的多線程調用方法,當使用alloc init的方式,需要手動啓動,便利構造器的方式不需要手動啓動
    //object,是線程回調方法的參數,如果不需要參數,直接賦予值爲nil;
    
    NSThread* forThread = [[NSThread alloc]initWithTarget:self selector:@selector(forMethod) object:nil];
    forThread.name = @"我是老二";
    //線程優先級,0到1.0
    forThread.threadPriority = 1.0;
    
    //啓動線程
    [forThread start];
    //得到當前線程的信息
    NSLog(@"imageThread---%@",[NSThread currentThread]);
    
    NSMutableArray* array = [NSMutableArray array];
    for (int j = 1; j<11; j++) {
        UIImage * item = [UIImage imageNamed:[NSString stringWithFormat:@"%d.jpg",j]];
        [array addObject:item];
    }
    imageView.animationImages = array;
    imageView.animationDuration = 2.0;
    //    imageView.animationRepeatCount = 10;
    //啓動動畫
    [imageView startAnimating];

}
//循環一億次
-(void)forMethod{
    NSLog(@"forThread---%@",[NSThread currentThread]);
    for(int i = 0;i<1000000;i++){
        NSLog(@"%d",i);
    }
}

效果就是可以看到動圖的加載並不受循環的影響,這就是線程的意義。

demo:
//nsthread學習
-(void)threadStudy{
    //便利構造器的方式,五返回值
    [NSThread detachNewThreadSelector:@selector(thread_1Action:) toTarget:self withObject:@"thread_1"];
    
    //通過alloc的方式創建
    NSThread *thread_2 = [[NSThread alloc]initWithTarget:self selector:@selector(thread_2Action:) object:@"thread_2"];
    [thread_2 start];
    thread_2.name = @"最優先";
    thread_2.threadPriority = 1.0;
    
    [NSThread detachNewThreadSelector:@selector(thread_3Action:) toTarget:self withObject:@"thread_3"];
}

-(void)thread_1Action:(NSString*)string{
    //當子線程是我們手動開闢的,那麼就需要我們自己管理內存
    @autoreleasepool {
        NSLog(@"%@",[NSThread currentThread]);
        NSLog(@"%@",string);
    }
    
    
}

-(void)thread_2Action:(NSString*)string{
    @autoreleasepool {
        NSLog(@"%@",[NSThread currentThread]);
        NSLog(@"%@",string);
    }
}

-(void)thread_3Action:(NSString*)string{
    @autoreleasepool {
        NSLog(@"%@",[NSThread currentThread]);
        NSLog(@"%@",string);
    }
}

記住線程如果是我們自己開闢的,那麼即使在mrc模式下,也需要將其放入自動釋放池中。

三、NSObject


 //NSObject的多線程方式
//    1.從主線程進入子線程
    [self performSelectorInBackground:@selector(objectAction:) withObject:@"090987開闢子線程的方式"];

在objectAction方法中,寫代碼並回到主線程:

-(void)objectAction:(NSString*)string{
    NSLog(@"參數%@",string);
    //從子線程中回到主線程
    /**
     *  Description
     *
     *  @param BOOL yes:只有回主線程的回調方法執行結束才執行下面的操作。NO:與之相反
     *
     *  @return 沒有返回值
     */
    [self performSelectorOnMainThread:@selector(backMainAction) withObject:nil waitUntilDone:NO];
    NSLog(@"我是在回主線程的底下打印的");
}

四、GCD



demo:
//串行隊列,一次只執行一個任務
-(void)serialQueue{
    //創建串行隊列
    /**
     *  Description
     *
     *  @param label#> 當前隊列的標籤 description#>
     *  @param attr#>  字符 description#>
     *
     *  @return 返回一個dispatch_queue_t
     */
    dispatch_queue_t serialQueue = dispatch_queue_create("串行隊列",DISPATCH_QUEUE_SERIAL);
    
    //爲串行隊列添加任務
    dispatch_async(serialQueue, ^{
        NSLog(@"你好------%@",[NSThread currentThread]);
    });
    //異步任務
    dispatch_async_f(serialQueue, "建華會說話了", function);
    dispatch_async(serialQueue, ^{
        NSLog(@"會上學了%@",[NSThread currentThread]);
    });
    dispatch_async(serialQueue, ^{
        NSLog(@"結婚了%@",[NSThread currentThread]);
    });
    dispatch_async(serialQueue, ^{
        NSLog(@"被全退了%@",[NSThread currentThread]);
    });
    dispatch_async(serialQueue, ^{
        NSLog(@"墮落了%@",[NSThread currentThread]);
    });
    dispatch_async(serialQueue, ^{
        NSLog(@"洗心革面了%@",[NSThread currentThread]);
    });
    dispatch_async(serialQueue, ^{
        NSLog(@"出家了%@",[NSThread currentThread]);
    });
    NSLog(@"我在最下面你%@",[NSThread currentThread]);
}

//定義一個回調函數
void function(void* str){
    printf("%s\n",str);
}

//創建並行隊列
-(void)concurrentQueue{
    
    //創建並行隊列
    dispatch_queue_t concurrentQueue = dispatch_queue_create("並行隊列", DISPATCH_QUEUE_CONCURRENT);
    //同步任務所處的線程就是當前線程
    
    dispatch_async(concurrentQueue, ^{
        NSLog(@"你好------%@",[NSThread currentThread]);
    });
    //異步任務
    dispatch_async_f(concurrentQueue, "建華會說話了", function);
    dispatch_async(concurrentQueue, ^{
        NSLog(@"會上學了%@",[NSThread currentThread]);
    });
    dispatch_async(concurrentQueue, ^{
        NSLog(@"結婚了%@",[NSThread currentThread]);
    });
    dispatch_async(concurrentQueue, ^{
        NSLog(@"被全退了%@",[NSThread currentThread]);
    });
    dispatch_async(concurrentQueue, ^{
        NSLog(@"墮落了%@",[NSThread currentThread]);
    });
    dispatch_async(concurrentQueue, ^{
        NSLog(@"洗心革面了%@",[NSThread currentThread]);
    });
    dispatch_async(concurrentQueue, ^{
        NSLog(@"出家了%@",[NSThread currentThread]);
    });
    
}

//系統提供的隊列,全局隊列
-(void)globalQueue{
    
    //系統提供的一個全局隊列
    //參數一,權限,即優先級 2,0 ,-2,INT16_MIN。參數二,系統預留
    dispatch_queue_t globalQueue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
    //添加任務
    //全局隊列是一個系統提供的並行隊列
    dispatch_async(globalQueue, ^{
        NSLog(@"*******--------------%@",[NSThread currentThread]);
    });
    dispatch_async(globalQueue, ^{
        NSLog(@"*******------36736735736737%@",[NSThread currentThread]);
    });
    dispatch_async(globalQueue, ^{
        NSLog(@"*******-37373756473637635%@",[NSThread currentThread]);
    });
    dispatch_async(globalQueue, ^{
        NSLog(@"******6666666666666666%@",[NSThread currentThread]);
    });
    dispatch_async(globalQueue, ^{
        NSLog(@"****555555555555555%@",[NSThread currentThread]);
    });
    dispatch_async(globalQueue, ^{
        NSLog(@"*******------%@",[NSThread currentThread]);
    });
    dispatch_async(globalQueue, ^{
        NSLog(@"*******----%@",[NSThread currentThread]);
    });
    dispatch_async(globalQueue, ^{
        NSLog(@"*******%@",[NSThread currentThread]);
    });
    
}
- (void)didReceiveMemoryWarning {
    [super didReceiveMemoryWarning];
    // Dispose of any resources that can be recreated.
}

//gcd常見的使用方式,全局隊列和主隊列結合使用
-(void)globalAndMainQueue{
    
    dispatch_async(dispatch_get_global_queue(0, 0), ^{
        //在全局隊列裏執行耗時的操作,因爲全局隊列執行的任務是在子線程中,不會阻塞主線程
        
        dispatch_async(dispatch_get_main_queue(), ^{
            //該block中所執行的任務是在主隊列中執行,那麼該任務是在主線程中執行,在此處進行刷新UI的行爲。
            
        });
    });
}

//gcd中讓某些代碼執行一次
-(void)onceToken{
    static UIImage* image = nil;
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        //此處的代碼只執行一次
        image = [[UIImage alloc]init];
    });
}

//其他的方法
-(void)otherGCD{
    
    //延時執行的
    dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(5 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
        NSLog(@"五秒真男人");
    });
    
    //重複執行
    dispatch_apply(3, dispatch_get_global_queue(0,0), ^(size_t size) {
        NSLog(@"五秒再來一次");
    });
    
}


五、隊列



demo:
//invocation的回調方法
-(void)invocationAction{
    //打印當前的線程
    
    NSLog(@"%@-------判斷是否爲主線程%d",[NSThread currentThread],[[NSThread currentThread] isMainThread]);
}
//operation和operationQueue
-(void)operationQueue{
    
    //初始化一個任務target - action operation並沒有開闢線程,將operation在那個線程中使用,operation所在的線程就是當前線程。
    NSInvocationOperation* invocation = [[NSInvocationOperation alloc]initWithTarget:self selector:@selector(invocationAction) object:nil];
    //當加入隊列的時候,不需要手動啓動,在隊列則不用手動啓動
    [invocation start];
    //操作的block的方式
    NSBlockOperation* blockOperation = [NSBlockOperation blockOperationWithBlock:^{
        NSLog(@"%@------",[NSThread currentThread]);
    }];
    //添加多個block操作,當使用addExecutionBlock爲BlockOPeration添加可執行的block的時候,這些可執行的block會在當前線程,或者其他子線程中進行。
    //在啓動之前添加事件
    for (int i=0; i<10; i++) {
        [blockOperation addExecutionBlock:^{
            NSLog(@"%@-----%d",[NSThread currentThread],i);
        }];
    };
    blockOperation.completionBlock = ^(){
        NSLog(@"我就是最後一個,你們隨便折騰");
    };
        //啓動操作
    [blockOperation start];
    NSLog(@"我是在最底下");
}

//queue的學習,隊列 nsoperationQuene 是對gcd的一個oc級別的封裝。
-(void)operationOperationQuene{
    
    //先初始化隊列對象,(其他隊列:除了主隊列,自己初始化的隊列都是其他隊列)
    NSOperationQueue *otherQueue = [[NSOperationQueue alloc]init];
    //隊列的最大併發數,在同一時刻最多可執行的操作
//    otherQueue.maxConcurrentOperationCount = 1;
    
    //創建可執行的操作對象
    /*for (int i=0; i<10; i++) {
        NSBlockOperation* blockopeartion = [NSBlockOperation blockOperationWithBlock:^{
            NSLog(@"%@-----%d",[NSThread currentThread],i);
        }];
        //將block操作添加到隊列中去
        [otherQueue addOperation:blockopeartion];
    };*/
    NSBlockOperation* blockopeartion_0 = [NSBlockOperation blockOperationWithBlock:^{
        NSLog(@"%@-----%d",[NSThread currentThread],0);
    }];
    NSBlockOperation* blockopeartion_1 = [NSBlockOperation blockOperationWithBlock:^{
        NSLog(@"%@-----%d",[NSThread currentThread],1);
    }];
    NSBlockOperation* blockopeartion_2 = [NSBlockOperation blockOperationWithBlock:^{
        NSLog(@"%@-----%d",[NSThread currentThread],2);
    }];
    NSBlockOperation* blockopeartion_3 = [NSBlockOperation blockOperationWithBlock:^{
        NSLog(@"%@-----%d",[NSThread currentThread],3);
    }];
    NSBlockOperation* blockopeartion_4 = [NSBlockOperation blockOperationWithBlock:^{
        NSLog(@"%@-----%d",[NSThread currentThread],4);
    }];
    //爲時間添加依賴關係,先添加依賴,在添加事件到隊列中
    [blockopeartion_4 addDependency:blockopeartion_3];
    
    //當操作對象添加到隊列中之後,就不需要手動啓動了
    [otherQueue addOperation:blockopeartion_0];
    [otherQueue addOperation:blockopeartion_1];
    [otherQueue addOperation:blockopeartion_2];
    [otherQueue addOperation:blockopeartion_3];
    [otherQueue addOperation:blockopeartion_4];
}

//主隊列
-(void)mainQueue{
    
    NSLog(@"%@",[NSThread currentThread]);
    //先創建主隊列的對象
    NSOperationQueue* mainQueue = [NSOperationQueue mainQueue];
    for (int i = 0 ; i < 10 ; i ++) {
        NSBlockOperation* blockOperation = [NSBlockOperation blockOperationWithBlock:^{
            NSLog(@"%@-----%d",[NSThread currentThread],i);
        }];
        [mainQueue addOperation:blockOperation];
    }
}


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