啥是抽象類? 抽象類是不完整的,它只能用做基類。在面向對象方法中,抽象類主要用來進行類型隱藏和充當全局變量的角色。 來自百度百科數組
NSOperationQueue *queue = [[NSOperationQueue alloc]init];
複製代碼
NSInvocationOperation *io = [[NSInvocationOperation alloc]initWithTarget:self selector:@selector(InvocationOperationSelector) object:nil];
[io start];
-(void)InvocationOperationSelector{
NSLog(@"這是NSInvocationOperation執行的任務 %@",[NSThread currentThread]);
}
複製代碼
輸出結果 bash
可知,在操做沒有添加到隊列中,操做直接start,任務是在主線程上執行,沒有開啓線程。多線程
NSBlockOperation *bo = [NSBlockOperation blockOperationWithBlock:^{
NSLog(@"這是NSBlockOperation執行的任務 %@",[NSThread currentThread]);
}];
[bo start];
複製代碼
輸出結果 併發
從結果來看,跟NSInvocationOperation
同理。嘗試將操做添加到隊列中看看輸出結果。
NSBlockOperation *bo = [NSBlockOperation blockOperationWithBlock:^{
NSLog(@"這是NSBlockOperation執行的任務 %@",[NSThread currentThread]);
}];
[bo addExecutionBlock:^{
NSLog(@"這是讓NSBlockOperation另外執行的任務 %@",[NSThread currentThread]);
}];
[bo addExecutionBlock:^{
NSLog(@"這是讓NSBlockOperation另外執行的任務2 %@",[NSThread currentThread]);
}];
[bo start];
複製代碼
輸出結果 函數
經過輸出結果可知,給操做添加額外任務,並不會讓這些任務按順序執行。可是初始化的任務仍然在主線程執行,另外兩個任務分別建立了線程。 因此NSBlockOperation
是否建立線程,取決於當前須要執行的任務數。 那麼,
blockOperationWithBlock
這裏面的任務就必定會在主線程執行嗎?咱們給上面的代碼加點戲,再看看打印結果。
NSBlockOperation *bo = [NSBlockOperation blockOperationWithBlock:^{
for (int i = 0; i<2; i++) {
[NSThread sleepForTimeInterval:2];
NSLog(@"這是NSBlockOperation執行的任務 %@",[NSThread currentThread]);
}
}];
[bo addExecutionBlock:^{
for (int i = 0; i<2; i++) {
[NSThread sleepForTimeInterval:2];
NSLog(@"這是讓NSBlockOperation另外執行的任務 %@",[NSThread currentThread]);
}
}];
[bo addExecutionBlock:^{
for (int i = 0; i<2; i++) {
[NSThread sleepForTimeInterval:2];
NSLog(@"這是讓NSBlockOperation另外執行的任務2 %@",[NSThread currentThread]);
}
}];
[bo start];
複製代碼
打印結果 ui
細心的小朋友已經發現了,blockOperationWithBlock
裏面的任務,並無在主線程執行啦。
因此,總結一下
1.NSBlockOperation
是否建立線程,取決於當前須要執行的任務數。
2.blockOperationWithBlock
裏面的任務,並無不必定主線程執行啦。spa
NSOperationQueue *queue = [[NSOperationQueue alloc]init];
NSInvocationOperation *io = [[NSInvocationOperation alloc]initWithTarget:self selector:@selector(InvocationOperationSelector) object:nil];
NSBlockOperation *bo = [NSBlockOperation blockOperationWithBlock:^{
for (int i = 0; i<2; i++) {
[NSThread sleepForTimeInterval:2];
NSLog(@"這是NSBlockOperation執行的任務 %@",[NSThread currentThread]);
}
}];
[queue addOperation:io];
[queue addOperation:bo];
複製代碼
輸出結果 線程
可見,兩個操做都分別建立了number爲3和4的線程,再也不是主線程。3d
注意:start
不能跟addOperation
同時使用,不然會致使崩潰 code
- (void)addDependency:(NSOperation *)op;
添加依賴,使當前操做依賴於操做 op 的完成。
- (void)removeDependency:(NSOperation *)op;
移除依賴,取消當前操做對操做 op 的依賴。
NSOperationQueue *queue = [[NSOperationQueue alloc]init];
NSBlockOperation *bo1 = [NSBlockOperation blockOperationWithBlock:^{
NSLog(@"這是bo1執行的任務 %@",[NSThread currentThread]);
}];
NSBlockOperation *bo2 = [NSBlockOperation blockOperationWithBlock:^{
NSLog(@"這是bo2執行的任務 %@",[NSThread currentThread]);
}];
NSBlockOperation *bo3 = [NSBlockOperation blockOperationWithBlock:^{
NSLog(@"這是bo3執行的任務 %@",[NSThread currentThread]);
}];
//bo1依賴於bo2
[bo1 addDependency:bo2];
//bo2依賴於bo3
[bo2 addDependency:bo3];
[queue addOperations:@[bo1,bo2,bo3] waitUntilFinished:YES];
NSLog(@"若是上面waitUntilFinished是YES,我就會最後執行");
複製代碼
輸出結果
waitUntilFinished
這裏面傳入的BOOL 值將會影響下面的代碼執行順序,若是是YES,將會造成一個相似同步函數、柵欄函數的同步功能。等隊列中的任務中都執行結束後才執行下面的代碼。
#####NSOperationQueue控制最大併發數(實現同步)
NSOperationQueue *queue = [[NSOperationQueue alloc]init];
queue.maxConcurrentOperationCount = 1;
NSBlockOperation *bo = [NSBlockOperation blockOperationWithBlock:^{
for (int i = 0; i<5; i++) {
NSLog(@"第%d次 執行任務 %@",i+1,[NSThread currentThread]);
}
}];
[bo addExecutionBlock:^{
for (int i = 0; i<5; i++) {
NSLog(@"第%d次 執行額外任務 %@",i+1,[NSThread currentThread]);
}
}];
[queue addOperation:bo];
複製代碼
先看輸出結果
從輸出結果能夠看出來一些東西任務
後執行
額外任務
,而是相互穿插。
任務
跟
額外任務
,卻按照12345的順序,老老實實的執行。
這裏
maxConcurrentOperationCount
控制的不是併發線程的數量,而是一個隊列中同時能併發執行任務的最大數。並且一個任務也並不是只能在一個線程中運行。
NSOperationQueue *queue = [[NSOperationQueue alloc]init];
UILabel *label = [[UILabel alloc]initWithFrame:CGRectMake(10, 100, 200, 10)];
[self.view addSubview:label];
NSBlockOperation *bo = [NSBlockOperation blockOperationWithBlock:^{
NSString * str = @"字符串賦值";
NSLog(@"這是子線程%@",[NSThread currentThread]);
[[NSOperationQueue mainQueue]addOperationWithBlock:^{
NSLog(@"回到主線程刷新UI%@",[NSThread currentThread]);
label.text = str;
}];
}];
[queue addOperation:bo];
複製代碼
打印以及顯示結果
1.取消操做方法
- (void)cancel;
可取消操做,實質是標記 isCancelled 狀態。
2.判斷操做狀態方法
- (BOOL)isFinished;
判斷操做是否已經結束。
- (BOOL)isCancelled;
判斷操做是否已經標記爲取消。
- (BOOL)isExecuting;
判斷操做是否正在在運行。
- (BOOL)isReady;
判斷操做是否處於準備就緒狀態,這個值和操做的依賴關係相關。
3.操做同步
- (void)waitUntilFinished;
阻塞當前線程,直到該操做結束。可用於線程執行順序的同步。
- (void)setCompletionBlock:(void (^)(void))block;
completionBlock 會在當前操做執行完畢時執行 completionBlock。
- (void)addDependency:(NSOperation *)op;
添加依賴,使當前操做依賴於操做 op 的完成。
- (void)removeDependency:(NSOperation *)op;
移除依賴,取消當前操做對操做 op 的依賴。
@property (readonly, copy) NSArray<NSOperation *> *dependencies;
在當前操做開始執行以前完成執行的全部操做對象數組。
1.取消/暫停/恢復操做
- (void)cancelAllOperations;
能夠取消隊列的全部操做。
- (BOOL)isSuspended;
判斷隊列是否處於暫停狀態。 YES 爲暫停狀態,NO 爲恢復狀態。
- (void)setSuspended:(BOOL)b;
可設置操做的暫停和恢復,YES 表明暫停隊列,NO 表明恢復隊列。
2.操做同步
- (void)waitUntilAllOperationsAreFinished;
阻塞當前線程,直到隊列中的操做所有執行完畢。
3.添加/獲取操做
- (void)addOperationWithBlock:(void (^)(void))block;
向隊列中添加一個 NSBlockOperation 類型操做對象。
- (void)addOperations:(NSArray *)ops waitUntilFinished:(BOOL)wait;
向隊列中添加操做數組,wait 標誌是否阻塞當前線程直到全部操做結束
- (NSArray *)operations;
當前在隊列中的操做數組(某個操做執行結束後會自動從這個數組清除)。
- (NSUInteger)operationCount;
當前隊列中的操做數。
4.獲取隊列
+ (id)currentQueue;
獲取當前隊列,若是當前線程不是在 NSOperationQueue 上運行則返回 nil。
+ (id)mainQueue;
獲取主隊列。
部分摘取自西單_夜未央