iOS多執行緒程式設計入門

hither發表於2017-12-13

##程式 執行緒 ##

  • 程式佔據記憶體,而執行緒佔據CPU。一個程式可以有多個執行緒,程式之間可以通過管道 或者套接字(Socket)進行通訊,而在一個程式中,多個執行緒相互之間可以直接 很方便的進行通訊。使用多執行緒程式設計可以幫助我們的程式減少 程式出現卡頓 假死這些情況的出現(不阻塞主執行緒的執行),使用起來可以極大的提升程式的使用者體驗,但是多執行緒也有一個不好的地方在於,你執行緒開得多了,對於其他程式來說就是一個不好的事情,其他程式佔用的資源就會變少。所以我們在使用多執行緒程式設計程式設計的時候要注意這點問題。

  • 下面是一個使用多執行緒中NSOperation 的一個例子:

    兩個按鈕模擬多執行緒 一個按鈕點選以後會睡眠10秒鐘 再執行的響應的內容 另外一個按鈕點選以後就會執行相應的內容 但是不適用多執行緒程式設計的時候 你點選了有睡眠的按鈕 第二個就不能點選了 因為第二個要等待第一個按鈕完成它的全部事件以後才會執行 這樣就造成了程式了卡頓 或者假死 所以這也是其我們要使用多執行緒程式設計的原因。

##程式碼區##

#import<UIKit/UIKit.h>

@interface ViewController : UIViewController

@end

複製程式碼

#import<UIKit/UIKit.h>

@interface ViewController ()

@end

@implementation ViewController 

- (void)viewDidLoad {

[super viewDidLoad];

}

- (void) foo:(UIButton *) button {

// 休眠和退出都是隻有正在執行的執行緒可以呼叫的方法

// 因此在設計上這兩個方法都是類方法而不是物件方法

// [NSThread exit];

// [NSThread sleepForTimeInterval:10]; 的作用和sleep(10)是一樣的

sleep(10);

NSLog(@"任務1已經完成!");

// 提示: 重新整理介面的操作要回到主執行緒處理否則有可能失效

// [self performSelectorOnMainThread:@selector(bar:) withObject:button waitUntilDone:YES];

// 建立一個操作物件

NSOperation *op = [[NSInvocationOperation alloc] initWithTarget:self selector:@selector(bar:) object:button];

// 向主執行緒佇列中新增操作物件(操作放到主執行緒中執行)

[[NSOperationQueue mainQueue] addOperation:op];

}

//重新整理介面以後 讓按鈕又可以再點選  讓按鈕的文字恢復

- (void) bar:(UIButton *) button {

button.enabled = YES;

[button setTitle:@"任務1" forState:UIControlStateNormal];

}

- (IBAction)blueButtonClicked:(UIButton *)sender {

// 提示: 對於那些耗時間的任務基本上都應該放到其他的執行執行緒中

// 不要阻塞主執行緒的執行 否則介面會出現卡頓或假死現象

// 模擬任務需要執行10秒鐘

[sender setTitle:@"正在執行..." forState:UIControlStateNormal];

sender.enabled = NO;

// 建立一個操作物件(待會要將該操作放到一個佇列中去執行)

NSOperation *op = [NSBlockOperation blockOperationWithBlock:^{

[self foo:sender];

}];

// 建立一個併發佇列

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

// 設定最大併發數量

queue.maxConcurrentOperationCount = 5;

// 向佇列中新增一個操作

[queue addOperation:op];

// [NSThread detachNewThreadSelector:@selector(foo:) toTarget:self withObject:sender];

// NSThread *thread = [[NSThread alloc] initWithTarget:self selector:@selector(foo:) object:sender];

// 啟動執行緒(執行foo回撥方法)

// [thread start];

// sleep(1);

// 提示: 如果執行緒已經開始執行則無法取消  --->如果不執行前面的那個sleep(1)   執行緒可以被取消但是 執行了sleep(1)以後執行緒就無法被取消了。

// [thread cancel];

// [self performSelectorInBackground:@selector(foo:) withObject:sender];

}

- (IBAction)yellowButtonClicked:(UIButton *)sender {

NSLog(@"任務2已經完成!");

}

@end
複製程式碼

補充說明: 補充一點: 如果我們的程式中 出現了多個執行緒競爭同一個資源的情況,這個時候 我們需要對這個資源進行同步保護(synchronized) 讓執行緒處於一個排隊狀態 ,當一個執行緒進入執行的時候,鎖被鎖上,然後其他程式無法進入。直到該執行緒完成了它的工作以後,它就會出來 然後鎖就會被開啟 然後其他執行緒就接著一個一個的執行。當然一個完成以後 另外一個進入的時候 並不是有順序排好隊的進入 就好比哪個運氣好 哪個就先進去。

  • 舉例說明:

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {

//建立一個可變字串作為多個執行緒共同競爭的一個資源

NSMutableString *mStr = [NSMutableString stringWithCapacity:10000];

//建立5個執行緒模擬競爭同一個資源

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

[NSThread detachNewThreadSelector:@selector(foo:) toTarget:self withObject:mStr];

}

return YES;

}

-(void)foo:(NSMutableString *)mStr{

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

@synchronized(mStr){

[mStr appendString:@"a"];

                            }

                   }
}
複製程式碼

相關文章