日韩av黄I国产麻豆传媒I国产91av视频在线观看I日韩一区二区三区在线看I美女国产在线I麻豆视频国产在线观看I成人黄色短片

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 >

多线程——NSThread、GCD、NSOperation

發(fā)布時間:2025/4/14 50 豆豆
生活随笔 收集整理的這篇文章主要介紹了 多线程——NSThread、GCD、NSOperation 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

1、前言:

一個應(yīng)用程序就是一個進程,一個進程至少包含一個線程,程序啟動會自動創(chuàng)建一個主線程,負責(zé)UI界面的現(xiàn)實和控件事件的監(jiān)控。多線程可以更充分的利用系統(tǒng)CPU資源,一定程度上提升程序的性能。1個進程可以開啟多條線程,每條線程可以并行(同時)執(zhí)行不同的任務(wù)。在一個線程內(nèi)可以包含多個事物(要干的活),在線程內(nèi)依據(jù)先進先出的特性串行執(zhí)行……

2、NSThread

- (void)viewDidLoad {[super viewDidLoad];NSLog(@"main thread is %@",[NSThread mainThread]);//打印主線程(UI線程) }-(void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event{//新開辟一條子線程,啟動子線程的時候調(diào)用downLoad方法,object是傳遞給子線程調(diào)用方法的參數(shù)NSThread *thread=[[NSThread alloc] initWithTarget:self selector:@selector(downLoad:) object:@"luseike"];//給子線程起一個名字thread.name=@"thread one";//開始子線程[thread start]; }-(void)downLoad:(NSString *)param{//打印當(dāng)前線程(子線程)及其名字和傳遞過來的參數(shù)NSLog(@"begin downLoad--param is %@--current thread is %@ current name is %@",param,[NSThread currentThread],[NSThread currentThread].name); }

?打印結(jié)果如下:

2014-06-26 23:03:05.724 NSThread[50292:60b] main thread is <NSThread: 0x8c421c0>{name = (null), num = 1}

2014-06-26 23:03:06.567 NSThread[50292:3807] begin downLoad--param is luseike--current thread is <NSThread: 0xa33c350>{name = thread one, num = 2} current name is thread one

可以看到主線程的num=1,子線程的num=2,證明確實是新開辟了一條線程來執(zhí)行downLoad操作。

還可以通過isMainThread判斷是否是主線程,setThreadPriority:(double)p來設(shè)置子線程的優(yōu)先級,優(yōu)先級的取值范圍在0.0~1.0之間,默認是0.5,值越大,優(yōu)先級越高,被執(zhí)行的幾率越大

還有兩種比較便捷的方式來創(chuàng)建子線程

1、[NSThread detachNewThreadSelector:@selector(downLoad:) toTarget:self withObject:@"luseike"];//  附加一個線程

2、[self performSelectorInBackground:@selector(downLoad:) withObject:@"haha"];  //在后臺執(zhí)行一個線程

這兩種方式創(chuàng)建的子線程都不需要調(diào)用start方法,系統(tǒng)會自動執(zhí)行對應(yīng)的方法,都也都沒有機會設(shè)置優(yōu)先級和咸線程名等更詳細的設(shè)置了,不過這個一般不重要

3、線程的狀態(tài)

線程從生到死大致有下面幾種狀態(tài):新建(new)、就緒(runnable)、運行(running)、阻塞(blocked)、死亡(dead)

一個線程被創(chuàng)建之后會放到一個叫做可調(diào)度線程池內(nèi),等待被CPU調(diào)度,當(dāng)該線程獲得CPU的執(zhí)行權(quán)時,就進入到running狀態(tài)。running狀態(tài)的線程如果調(diào)用sleep方法或者在等待同步鎖,就會進入阻塞狀態(tài),進入阻塞狀態(tài)的線程會重新被放到可調(diào)度線程池內(nèi),等待被重新調(diào)度。線程任務(wù)執(zhí)行完畢,或者被強制退出,會進入dead狀態(tài),注意:進入dead狀態(tài)的線程并沒有被釋放內(nèi)存,只是不能用了而已,還存在內(nèi)存中。

?

4、控制線程的狀態(tài)

啟動線程:之前介紹過,調(diào)用start方法

阻塞(暫停)線程:

  + (void)sleepUntilDate:(NSDate *)date;

  + (void)sleepForTimeInterval:(NSTimeInterval)ti;

強制停止線程:+(void)exit;

多線程的安全隱患:當(dāng)多個線程訪問同一塊資源時,很容易引發(fā)數(shù)據(jù)錯亂和數(shù)據(jù)安全問題。解決的機制就是使用鎖(互斥鎖),讓多條線程同步執(zhí)行,這就是傳說的線程同步技術(shù)。值得注意的是:鎖定一份代碼只用1把鎖,用多把鎖是沒有意義的;線程同步的前提是多條線程搶占同一塊資源

#import "ViewController.h"@interface ViewController () @property(nonatomic,strong)NSThread *thread1; @property(nonatomic,strong)NSThread *thread2; @property(nonatomic,strong)NSThread *thread3;@property(nonatomic,assign)int totalCount; @end@implementation ViewController- (void)viewDidLoad {[super viewDidLoad];self.totalCount=100;self.thread1=[[NSThread alloc] initWithTarget:self selector:@selector(saleTicket) object:nil];self.thread2=[[NSThread alloc] initWithTarget:self selector:@selector(saleTicket) object:nil];self.thread3=[[NSThread alloc] initWithTarget:self selector:@selector(saleTicket) object:nil]; }-(void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event{[self.thread1 start];[self.thread2 start];[self.thread3 start]; }-(void)saleTicket{int leftCount=self.totalCount;while (leftCount>0) {self.totalCount=leftCount--;NSLog(@"%@ sale one ticket,left %d",[NSThread currentThread],leftCount);}
} @end

?如上代碼,模擬3個子線程同時訪問公共資源totalCount,每次操作減一,多線程訪問同一資源容易引起的數(shù)據(jù)安全問題已經(jīng)說明了,打印部分結(jié)果如下

2014-06-26 23:51:33.639 NSThread[63065:360b] <NSThread: 0xa06dd50>{name = (null), num = 3} sale one ticket,left 99

2014-06-26 23:51:33.639 NSThread[63065:3707] <NSThread: 0xa0706e0>{name = (null), num = 2} sale one ticket,left 99

2014-06-26 23:51:33.639 NSThread[63065:3f03] <NSThread: 0xa06ddf0>{name = (null), num = 4} sale one ticket,left 99

可以看到三個子線程都操作了totalCount變量,每次操作之后的值卻沒有變化……

互斥鎖的使用格式:

@synchronized(鎖對象) { // 需要鎖定的代碼? }

-(void)saleTicket{while (1) {@synchronized(self) { // 加鎖(只能用一把鎖)// 1.先檢查票數(shù)int count = self.totalCount;if (count > 0) {self.totalCount = count - 1;NSThread *current = [NSThread currentThread];NSLog(@"%@ sale one ticket, left %d tickets", current, self.totalCount);} else {[NSThread exit];}} } }

?打印結(jié)果就可以正常顯示了……

5、GCD簡介

GCD是蘋果為了多核的并行運算提出的解決方案,會自動管理線程的生命周期,程序員只需要告訴GCD要執(zhí)行什么任務(wù),不需要編寫任何線程管理代碼。GCD中兩個核心概念:任務(wù)、隊列,將任務(wù)添加到隊列中,GCD會自動將隊列中的任務(wù)取出,放到對應(yīng)的線程中執(zhí)行,任務(wù)的取出遵循隊列FIFO原則:先進先出,后進后出。

GCD的隊列可以分為2大類型:并發(fā)隊列(可以讓多個任務(wù)并發(fā)執(zhí)行)、串行隊列

?

轉(zhuǎn)載于:https://www.cnblogs.com/luseike/p/3811128.html

總結(jié)

以上是生活随笔為你收集整理的多线程——NSThread、GCD、NSOperation的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。