NSLog(@"%@",[NSThread currentThread]);//獲取當前線程,當打印的number等於1時,表明當前是主線程,大於1表明子線程
thread = [[NSThreadalloc] initWithTarget:selfselector:@selector(run1:) object:@"123"];
[NSThread detachNewThreadSelector:@selector(run2) toTarget:self withObject:nil];
3) [self performSelectorOnMainThread:@selector(test) withObject:nil waitUntilDone:NO];//跳入主線程的方法,第一個參數表明要調用的方法,第二個參數表明傳的值,第三個參數表明是否等待此操做完成後再繼續往下執行
5) [self performSelector:@selector(test) withObject:nil afterDelay:3];//延遲調用
NSLog(@"%@",[NSThread currentThread]);//獲取當前線程,當打印的number等於1時,表明當前是主線程,大於1表明子線程
[r runMode:NSDefaultRunLoopMode beforeDate:[NSDate distantFuture]];//runMode 第一個參數表明消息方式,默認寫NSDefaultRunLoopMode,第二個參數表明結束時間,通常給distantFuture,表明不可達到的將來某個時間
//* [self performSelectorOnMainThread:@selector(test) withObject:nil waitUntilDone:NO];//跳入主線程的方法,第一個參數表明要調用的方法,第二個參數表明傳的值,第三個參數表明是否等待此操做完成後再繼續往下執行
//* [self performSelector:@selector(test) withObject:nil];//在當前線程執行另一個方法
//*延遲調用 [self performSelector:<#(nonnull SEL)#> withObject:<#(nullable id)#> afterDelay:<#(NSTimeInterval)#>]
[self performSelector:@selector(run3) onThread:thread withObject:nil waitUntilDone:NO];//在某個線程中執行某個方法
3、 Cocoa NSOperation
優勢:不須要關心線程管理,數據同步的事情,能夠把精力放在本身須要執行的操做上。
NSOperation實例封裝了須要執行的操做和執行操做所需的數據,而且可以以併發或非併發的方式執行這個操做。
NSOperation自己是抽象基類,所以必須使用它的子類,使用NSOperation子類的方式有2種:一種是用定義好的兩個子類:NSInvocationOperation 和 NSBlockOperation,另外一種是自定義子類繼承NSOperation,實現內部相應的方法
一、 NSOperation的做用:配合使用NSOperation和NSOperationQueue也能實現多線程編程取消操做
二、 NSOperation和NSOperationQueue實現多線程的具體步驟:
先將須要執行的操做封裝到一個NSOperation對象中
而後將NSOperation對象添加到NSOperationQueue中
系統會⾃動將NSOperationQueue中的NSOperation取出來
將取出的NSOperation封裝的操做放到⼀條新線程中執⾏
二、建立操做對象,封裝要執行的任務
//NSInvocationOperation 封裝操做
NSInvocationOperation *operation = [[NSInvocationOperation alloc]initWithTarget:self selector:@selector(run1) object:nil];
NSInvocationOperation *operation1 = [[NSInvocationOperation alloc]initWithTarget:self selector:@selector(run1) object:nil];
三、執行操做
[operation start];
[operation1 start];
注意:操做對象默認在主線程中執行,只有添加到隊列中才會開啓新的線程。即默認狀況下,若是操做沒有放到隊列queue中,都是同步執行。只有將NSOperation放到一個
四、NSBlockOperation建立操做對象
NSBlockOperation *block = [NSBlockOperation blockOperationWithBlock:^{
NSLog(@"block操做:%@",[NSThread currentThread]);
}];
//在NSBlockOperation對象中添加一個操做,若是NSBlockOperation對象包含了多個操做,有一個是在主線中一行,其餘均在子線程中執行
五、添加操做(注意添加要放在start以前)
[block addExecutionBlock:^{
NSLog(@"block操做2:%@",[NSThread currentThread]);
}];
[block addExecutionBlock:^{
NSLog(@"block操做3:%@",[NSThread currentThread]);
}];
[block addExecutionBlock:^{
NSLog(@"block操做4:%@",[NSThread currentThread]);
}];
六、執行操做
[block start ];//注意添加要放在start以前
七、NSOperationQueue:建立隊列:將操做放入隊列(主隊列除外),默認在子線程中執行,且不須要手動start
1)NSOperationQueue的做⽤:NSOperation能夠調⽤start⽅法來執⾏任務,但默認是同步執行的
若是將NSOperation添加到NSOperationQueue(操做隊列)中,系統會自動異步執行NSOperation中的操做
添加操做到NSOperationQueue中,自動執行操做,自動開啓線程
2)建立NSOperationQueue
NSOperationQueue *queue = [[NSOperationQueue alloc]init];
NSInvocationOperation *ioperation = [[NSInvocationOperation alloc]initWithTarget:self selector:@selector(run2) object:nil];
八、把操做添加到隊列中
1)第一種:添加以前建立的
[queue addOperation:ioperation];
2)第二種:添加的時候建立
注意:使用NSOperationQueue時,無需start
[queue addOperationWithBlock:^{
NSLog(@"block操做隊列:%@",[NSThread currentThread]);
}];
九、事件的實現
-(void)run1{
NSLog(@"執行操做:%@",[NSThread currentThread]);
}
-(void)run2{
NSLog(@"隊列中執行:%@",[NSThread currentThread]);
}
4、GCD 全稱:Grand Central Dispatch
一、Grand Central Dispatch (GCD)是Apple開發的一個多核編程的解決方法。在iOS4.0開始以後才能使用。GCD是一個替代諸如NSThread, NSOperationQueue, NSInvocationOperation等技術的很高效和強大的技術。
二、GCD的工做原理是:讓程序平行排隊的特定任務,根據可用的處理資源,安排他們在任何可用的處理器核心上執行任務
三、 GCD是基於C語言的。若是使用GCD,徹底由系統管理線程,咱們不須要編寫線程代碼。只需定義想要執行的任務,而後添加到適當的調度隊列(dispatch queue)。GCD會負責建立線程和調度你的任務,系統直接提供線程管理
四、經常使用的方法dispatch_async
爲了不界面在處理耗時的操做時卡死,好比讀取網絡數據,IO,數據庫讀寫等,咱們會在另一個線程中處理這些操做,而後通知主線程更新界面。
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
// 耗時的操做
dispatch_async(dispatch_get_main_queue(), ^{
// 更新界面
});
});
dispatch_async開啓一個異步操做,第一個參數是指定一個gcd隊列,第二個參數是分配一個處理事物的程序塊到該隊列。
dispatch_get_global_queue(0, 0),指用了全局隊列。
通常來講系統自己會有3個隊列:global_queue、current_queue(廢棄)和main_queue
獲取一個全局隊列是接受兩個參數,第一個是我分配的事物處理程序塊隊列優先級。分高低和默認,0爲默認2爲高,-2爲低
五、dispatch_group_async的使用
dispatch_group_async能夠實現監聽一組任務是否完成,完成後獲得通知執行其餘的操做。這個方法頗有用,好比你執行三個下載任務,當三個任務都下載完成後你才通知界面說完成了。
1)建立一個組
dispatch_group_t group = dispatch_group_create();
2)在一個組內提交一個代碼塊來執行。必須明確這個代碼塊屬於哪一個組,必須 在哪一個派送隊列上執行。
dispatch_group_async(group, queue, ^{
NSLog(@"group1--%@",[NSThread currentThread]);
});
dispatch_group_async(group, queue, ^{
NSLog(@"group2--%@",[NSThread currentThread]); });
dispatch_group_async(group, queue, ^{
NSLog(@"group3--%@",[NSThread currentThread]); });
3)等待組中的任務執行完畢,回到主線程執行block回調
dispatch_group_notify(group, dispatch_get_main_queue(), ^{
NSLog(@"updateUi");
});
六、dispatch_barrier_async
dispatch_barrier_async是在前面的任務執行結束後它才執行,並且它後面的任務等它執行完成以後纔會執行
//建立隊列,第一個參數表明隊列名,第二個表明串行仍是並行:DISPATCH_QUEUE_SERIAL串行 DISPATCH_QUEUE_CONCURRENT 並行
dispatch_queue_t queue = dispatch_queue_create("123", DISPATCH_QUEUE_SERIAL);
dispatch_async(queue, ^{
NSLog(@"dispatch_async1");
});
//上一步執行結束才執行這一步
dispatch_barrier_async(queue, ^{
NSLog(@"dispatch_barrier_async");
});
//執行完上一步才執行下一步
dispatch_async(queue, ^{
NSLog(@"dispatch_async3");
});
七、dispatch_apply
它通常都是放在dispatch_async裏面(異步)。
執行某個代碼片斷N次
dispatch_async(dispatch_get_global_queue(0, 0), ^{
dispatch_apply(5, dispatch_get_global_queue(0, 0), ^(size_t index) {
NSLog(@"%ld",index);
});
});
八、具體代碼
#import "ViewController.h"
@interface ViewController ()
@end
@implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
UIImageView *imageview = [[UIImageView alloc]initWithFrame:CGRectMake(10, 30, 100, 100)];
[self.view addSubview:imageview];
UIImageView *imageview1 = [[UIImageView alloc]initWithFrame:CGRectMake(30, 150, 100, 100)];
[self.view addSubview:imageview1];
UIImageView *imageview2 = [[UIImageView alloc]initWithFrame:CGRectMake(30, 270, 100, 100)];
[self.view addSubview:imageview2];
UIImageView *imageview3 = [[UIImageView alloc]initWithFrame:CGRectMake(30, 390, 100, 100)];
[self.view addSubview:imageview3];
dispatch_async(dispatch_get_global_queue(0, 0), ^{
//NSLog(@"耗時操做:%@",[NSThread currentThread]);
NSData *data = [NSData dataWithContentsOfURL:[NSURL URLWithString:@"
http://www.yooyoo360.com/photo/2009-1-1/20090112132752467.jpg"]];
UIImage *image = [UIImage imageWithData:data];
//NSLog(@"---%@",image);
//返回主線程
dispatch_async(dispatch_get_main_queue(), ^{
//NSLog(@"更新UI:%@",[NSThread currentThread]);
imageview.image = image;
});
});
//組
//建立組,用於存放耗時操做
dispatch_group_t group = dispatch_group_create();
__block UIImage *image,*image1,*image2,*image3;
//將操做封裝進組,第一個參數表明要存放操做的組名,第二個參數表明操做隊列,block執行耗時操做
//在一個組內提交一個代碼塊來執行。必須明確這個代碼塊屬於哪一個組,必須在哪一個派送隊列上執行。
dispatch_group_async(group, dispatch_get_global_queue(0, 0), ^{
image1 = [UIImage imageWithData:data];
//NSLog(@"==%@",image1);
});
});
dispatch_group_async(group, dispatch_get_global_queue(0, 0), ^{
image3 = [UIImage imageWithData:data];
//NSLog(@"----%@",image);
});
//監聽一組操做,第一個參數表明要監聽的組名,第二個參數表明一組操做徹底結束後跳轉到哪一個隊列,通常跳到主線程(dispatch_get_main_queue),block執行要進行的操做(通常用來更新UI),注意:此方法在組中的全部操做執行完畢後調用
//等待組中的任務執行完畢,回到主線程執行block回調
dispatch_group_notify(group, dispatch_get_main_queue(), ^{
imageview.image = image;
imageview1.image = image1;
imageview2.image = image2;
imageview3.image = image3;
});
}
-(void)didReceiveMemoryWarning {
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
@end