一、NSthread的初始化
1.動態(tài)方法
-(id)initWithTarget:(id)target selector:(SEL)selector object:(id)argument;
// 初始化線程
NSThread *thread = [[NSThread alloc] initWithTarget:self selector:@selector(run) object:nil];
// 設(shè)置線程的優(yōu)先級(0.0 - 1.0,1.0最高級)
thread.threadPriority = 1;
// 開啟線程
[thread start];
參數(shù)解析:
selector :線程執(zhí)行的方法,這個selector最多只能接收一個參數(shù)
target :selector消息發(fā)送的對象
argument : 傳給selector的唯一參數(shù),也可以是nil
2.靜態(tài)方法
+ (void)detachNewThreadSelector:(SEL)selector toTarget:(id)target withObject:(id)argument;
[NSThread detachNewThreadSelector:@selector(downloagImage:) toTarget:self withObject:@"http://h.hiphotos.baidu.com/zhidao/pic/item/6a63f6246b600c3320b14bb3184c510fd8f9a185.jpg"];
-(void)downloagImage:(NSString*)url
{
NSData *data = [[NSData alloc] initWithContentsOfURL:[NSURL URLWithString:url]];
UIImage *image= [[UIImage alloc] initWithData:data];
if (image) {
[self performSelectorOnMainThread:@selector(updateUI:) withObject:image waitUntilDone:YES];
}
}
3.隱式創(chuàng)建線程的方法
[self performSelectorInBackground:@selector(run) withObject:nil];
4.獲取當(dāng)前線程
NSThread *current = [NSThread currentThread];
5.獲取主線程
NSThread *main = [NSThread mainThread];
6.在指定線程上執(zhí)行操作
[self performSelector:@selector(run) onThread:thread withObject:nil waitUntilDone:YES];
7.在主線程上執(zhí)行操作
[self performSelectorOnMainThread:@selector(run) withObject:nil waitUntilDone:YES];
8.在當(dāng)前線程執(zhí)行操作
[self performSelector:@selector(run) withObject:nil];
9.優(yōu)缺點
1.優(yōu)點:NSThread比其他兩種多線程方案較輕量級,更直觀地控制線程對象
2.缺點:需要自己管理線程的生命周期,線程同步。線程同步對數(shù)據(jù)的加鎖會有一定的系統(tǒng)開銷
二、GCD
6種
并行隊列 + 同步執(zhí)行(不會開啟新線程)
并行隊列 + 異步執(zhí)行(可同時開啟多線程,任務(wù)交替執(zhí)行)
串行隊列 + 同步執(zhí)行(不會開啟新線程)
串行隊列 + 異步執(zhí)行(可同時開啟多線程)
主隊列 + 同步執(zhí)行 ***互等卡住不可行
主隊列 + 異步執(zhí)行 ***執(zhí)行完一個任務(wù),再執(zhí)行下一個任務(wù)
// 串行隊列的創(chuàng)建方法
dispatch_queue_t queue= dispatch_queue_create("test.queue", DISPATCH_QUEUE_SERIAL);
// 并行隊列的創(chuàng)建方法
dispatch_queue_t queue= dispatch_queue_create("test.queue", DISPATCH_QUEUE_CONCURRENT);
// 同步執(zhí)行任務(wù)創(chuàng)建方法
dispatch_sync(queue, ^{
NSLog(@"%@",[NSThread currentThread]); // 這里放任務(wù)代碼
});
// 異步執(zhí)行任務(wù)創(chuàng)建方法
dispatch_async(queue, ^{
NSLog(@"%@",[NSThread currentThread]); // 這里放任務(wù)代碼
});
1.柵欄方法 dispatch_barrier_async,在執(zhí)行完柵欄前面的操作之后,才執(zhí)行柵欄操作,最后再執(zhí)行柵欄后邊的操作
dispatch_barrier_async(queue, ^{
NSLog(@"----barrier-----%@", [NSThread currentThread]);
});
2.延時執(zhí)行方法 dispatch_after
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(2.0 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
// 2秒后異步執(zhí)行這里的代碼...
NSLog(@"run-----");
});
3.一次性代碼(只執(zhí)行一次) dispatch_once(單例)
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
// 只執(zhí)行1次的代碼(這里面默認是線程安全的)
});
4.快速迭代方法 dispatch_apply
dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
dispatch_apply(6, queue, ^(size_t index) {
NSLog(@"%zd------%@",index, [NSThread currentThread]);
});
5.隊列組 dispatch_group
dispatch_group_t group = dispatch_group_create();
dispatch_group_async(group, dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
// 執(zhí)行1個耗時的異步操作
});
dispatch_group_async(group, dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
// 執(zhí)行1個耗時的異步操作
});
dispatch_group_notify(group, dispatch_get_main_queue(), ^{
// 等前面的異步操作都執(zhí)行完畢后,回到主線程...
});
三、NSOperation
1. 使用子類- NSInvocationOperation:
// 1.創(chuàng)建NSInvocationOperation對象
NSInvocationOperation *op = [[NSInvocationOperation alloc] initWithTarget:self selector:@selector(run) object:nil];
// 2.調(diào)用start方法開始執(zhí)行操作
[op start];
- (void)run
{
NSLog(@"------%@", [NSThread currentThread]);
}
在沒有使用NSOperationQueue、單獨使用NSInvocationOperation的情況下,NSInvocationOperation在主線程執(zhí)行操作,并沒有開啟新線程
2.使用子類- NSBlockOperation
NSBlockOperation *op = [NSBlockOperation blockOperationWithBlock:^{
// 在主線程
NSLog(@"------%@", [NSThread currentThread]);
}];
[op start];
在沒有使用NSOperationQueue、單獨使用NSBlockOperation的情況下,NSBlockOperation也是在主線程執(zhí)行操作,并沒有開啟新線程
但是,NSBlockOperation還提供了一個方法addExecutionBlock:,通過addExecutionBlock:就可以為NSBlockOperation添加額外的操作,這些額外的操作就會在其他線程并發(fā)執(zhí)行。
- (void)blockOperation
{
NSBlockOperation *op = [NSBlockOperation blockOperationWithBlock:^{
// 在主線程
NSLog(@"1------%@", [NSThread currentThread]);
}];
// 添加額外的任務(wù)(在子線程執(zhí)行)
[op addExecutionBlock:^{
NSLog(@"2------%@", [NSThread currentThread]);
}];
[op addExecutionBlock:^{
NSLog(@"3------%@", [NSThread currentThread]);
}];
[op addExecutionBlock:^{
NSLog(@"4------%@", [NSThread currentThread]);
}];
[op start];
}
blockOperationWithBlock:方法中的操作是在主線程中執(zhí)行的,而addExecutionBlock:方法中的操作是在其他線程中執(zhí)行的
3.將任務(wù)加入到隊列中
(1).- (void)addOperation:(NSOperation *)op;需要先創(chuàng)建任務(wù),再將創(chuàng)建好的任務(wù)加入到創(chuàng)建好的隊列中去
- (void)addOperationToQueue
{
// 1.創(chuàng)建隊列
NSOperationQueue *queue = [[NSOperationQueue alloc] init];
// 2. 創(chuàng)建操作
// 創(chuàng)建NSInvocationOperation
NSInvocationOperation *op1 = [[NSInvocationOperation alloc] initWithTarget:self selector:@selector(run) object:nil];
// 創(chuàng)建NSBlockOperation
NSBlockOperation *op2 = [NSBlockOperation blockOperationWithBlock:^{
for (int i = 0; i < 2; ++i) {
NSLog(@"1-----%@", [NSThread currentThread]);
}
}];
// 3. 添加操作到隊列中:addOperation:
[queue addOperation:op1]; // [op1 start]
[queue addOperation:op2]; // [op2 start]
}
- (void)run
{
for (int i = 0; i < 2; ++i) {
NSLog(@"2-----%@", [NSThread currentThread]);
}
}
NSInvocationOperation和NSOperationQueue結(jié)合后能夠開啟新線程,進行并發(fā)執(zhí)行NSBlockOperation和NSOperationQueue也能夠開啟新線程,進行并發(fā)執(zhí)行
(2).- (void)addOperationWithBlock:(void (^)(void))block;無需先創(chuàng)建任務(wù),在block中添加任務(wù),直接將任務(wù)block加入到隊列中
- (void)addOperationWithBlockToQueue
{
// 1. 創(chuàng)建隊列
NSOperationQueue *queue = [[NSOperationQueue alloc] init];
// 2. 添加操作到隊列中:addOperationWithBlock:
[queue addOperationWithBlock:^{
for (int i = 0; i < 2; ++i) {
NSLog(@"-----%@", [NSThread currentThread]);
}
}];
}
能夠開啟新線程,進行并發(fā)執(zhí)行
4.控制串行執(zhí)行和并行執(zhí)行的關(guān)鍵
最大并發(fā)數(shù):maxConcurrentOperationCount
maxConcurrentOperationCount默認情況下為-1,表示不進行限制,默認為并發(fā)執(zhí)行。
當(dāng)maxConcurrentOperationCount為1時,進行串行執(zhí)行。
當(dāng)maxConcurrentOperationCount大于1時,進行并發(fā)執(zhí)行,當(dāng)然這個值不應(yīng)超過系統(tǒng)限制,即使自己設(shè)置一個很大的值,系統(tǒng)也會自動調(diào)整。
// 創(chuàng)建隊列
NSOperationQueue *queue = [[NSOperationQueue alloc] init];
// 設(shè)置最大并發(fā)操作數(shù)
// queue.maxConcurrentOperationCount = 2;
queue.maxConcurrentOperationCount = 1; // 就變成了串行隊列
5.操作依賴
NSOperation和NSOperationQueue最吸引人的地方是它能添加操作之間的依賴關(guān)系。比如說有A、B兩個操作,其中A執(zhí)行完操作,B才能執(zhí)行操作,那么就需要讓B依賴于A。具體如下
- (void)addDependency
{
NSOperationQueue *queue = [[NSOperationQueue alloc] init];
NSBlockOperation *op1 = [NSBlockOperation blockOperationWithBlock:^{
NSLog(@"1-----%@", [NSThread currentThread]);
}];
NSBlockOperation *op2 = [NSBlockOperation blockOperationWithBlock:^{
NSLog(@"2-----%@", [NSThread currentThread]);
}];
[op2 addDependency:op1]; // 讓op2 依賴于 op1,則先執(zhí)行op1,在執(zhí)行op2
[queue addOperation:op1];
[queue addOperation:op2];
}
6.一些其他方法
- (void)cancel;NSOperation提供的方法,可取消單個操作
- (void)cancelAllOperations;NSOperationQueue提供的方法,可以取消隊列的所有操作
- (void)setSuspended:(BOOL)b;可設(shè)置任務(wù)的暫停和恢復(fù),YES代表暫停隊列,NO代表恢復(fù)隊列
- (BOOL)isSuspended;判斷暫停狀態(tài)
注意:
這里的暫停和取消并不代表可以將當(dāng)前的操作立即取消,而是當(dāng)當(dāng)前的操作執(zhí)行完畢之后不再執(zhí)行新的操作。
暫停和取消的區(qū)別就在于:暫停操作之后還可以恢復(fù)操作,繼續(xù)向下執(zhí)行;而取消操作之后,所有的操作就清空了,無法再接著執(zhí)行剩下的操作。