多線程

ViewController.h

#import <UIKit/UIKit.h>

@interface ViewController : UIViewController


@end

ViewController.m


#import "ViewController.h"

@interface ViewController ()

@property(nonatomic,strong)NSLock *lock; // 系統(tǒng)提供好的鎖類

@end


void function(void *str){
    NSLog(@"這是個函數(shù)!GCD最下面自定義隊(duì)列在用! %s",str);
}




int count = 10000;






@implementation ViewController

- (void)viewDidLoad {
    [super viewDidLoad];
    
    self.lock = [[NSLock alloc]init];
    
    
}


// 五個按鈕的五個方法

- (IBAction)normalAction:(UIButton *)sender {
    NSLog(@"普通計(jì)算");
    [self test];
    
}
// 封裝計(jì)算的方法
-(void)test{
    // 打印當(dāng)前線程, 當(dāng)前線程是否是主線程
    NSLog(@"%@,%d",[NSThread currentThread],[[NSThread currentThread]isMainThread]);
    
    // 自動釋放池 (autoreleasepool)
    // 在iOS里面,會自動為UI創(chuàng)建一個主線程,默認(rèn)主線程分配的內(nèi)存空間是1M,我們新開辟的子線程默認(rèn)是512k,分配的大小必須是4的倍數(shù),分配給子線程的空間,是用來存儲變量的,所以512k是充分夠用的
    // iOS運(yùn)行的時候,程序在主入口自動添加自動釋放池,而我們自己創(chuàng)建的子線程是沒有自動釋放池的,所以需要我們手動添加
    // 添加釋放池的原因: 子線程共用堆內(nèi)存,如果不及時回收,隨著子線程數(shù)量的上升,以及大量使用便利構(gòu)造器,會對系統(tǒng)本身造成很大的負(fù)擔(dān)
    @autoreleasepool {
        // 計(jì)算1到635500000
        NSUInteger sum = 0;
        for (NSUInteger i = 0; i <= 635500000; i++) {
            sum += i;
        }
        NSLog(@"%ld",sum);
    }
    
    
    
    
    // ******  子線程回到主線程  ******  (線程間的通信)  ******
    // GCD
    dispatch_async(dispatch_get_main_queue(), ^{
            // 在這里面進(jìn)行主線程任務(wù)的操作(UI刷新)
    });
    // NSObject自帶的方法
    // (1)
    [self performSelectorOnMainThread:@selector(backMainThread) withObject:nil waitUntilDone:YES];
    // (2)
    [self performSelector:@selector(backMainThread) onThread:[NSThread mainThread] withObject:nil waitUntilDone:YES];
    
    

}

-(void)backMainThread{
    NSLog(@"在該方法內(nèi)實(shí)現(xiàn)主線程UI的刷新");
}

#pragma mark    - NSObject
- (IBAction)nsobjectAction:(UIButton *)sender {
    NSLog(@"NSObject");
    // 在后臺執(zhí)行 (開辟多線程最簡單的方法)
    [self performSelectorInBackground:@selector(test) withObject:nil];
    
}
#pragma mark    - NSThread
- (IBAction)nsthreadAction:(UIButton *)sender {
    NSLog(@"NSThread");
    
    // NSThread 是一個輕量級的多線程, 創(chuàng)建方式有兩種
    // 第一種:
    
         // 1.由init來創(chuàng)建, 并且需要手動開啟
//    NSThread *thread = [[NSThread alloc]initWithTarget:self selector:@selector(test) object:nil];
//        // 2.開啟線程
//    [thread start];
//        // 3.取消線程
//    [thread cancel]; // 不需要的時候?qū)懰?一般很少用
    
    
    // 第二種:
    // 初始化的同時自動開啟子線程
    [NSThread detachNewThreadSelector:@selector(test) toTarget:self withObject:nil];

}
#pragma mark    - NSOperation
- (IBAction)oprerationAction:(UIButton *)sender {
    NSLog(@"NSOperationQueue");
    
    // NSOperation 是一個抽象類,它有兩個子類,一個是NSInvocationOperation,另一個是NSBlockOperation
    // 在MVC里面屬于M層, 封裝了單個任務(wù)的數(shù)據(jù)和相關(guān)的代碼, 一般我們使用子類
    // NSOperation 只是一個操作,本身并無主線程子線程的區(qū)分,通常與NSOperationQueue結(jié)合使用
    
    // NSInvocationOperation
//    NSInvocationOperation *invocationOperation = [[NSInvocationOperation alloc]initWithTarget:self selector:@selector(test) object:nil];
//    
//    // NSBlockOperation
    __weak typeof(self)temp = self;
//    NSBlockOperation *blockOperation = [NSBlockOperation blockOperationWithBlock:^{
//        [temp test];
//        NSLog(@"這個是blockOperation操作之行的");
//
//    }];
    
    
    NSBlockOperation *blockOperation1 = [NSBlockOperation blockOperationWithBlock:^{
        [temp test1];
    }];
    NSInvocationOperation *invocation2 = [[NSInvocationOperation alloc]initWithTarget:self selector:@selector(test2) object:nil];
    NSBlockOperation *blockOperation2 = [NSBlockOperation blockOperationWithBlock:^{
        [temp test3];
    }];
    
    
    
    // NSOperationQueue 是線程操作隊(duì)列,用來管理一組Operation對象,會根據(jù)實(shí)際需求創(chuàng)建出合適數(shù)量的子線程,完成任務(wù)的并發(fā)執(zhí)行
    NSOperationQueue *queue = [[NSOperationQueue alloc]init];
    
    // 設(shè)置最大并發(fā)執(zhí)行數(shù)(當(dāng)最大并發(fā)執(zhí)行數(shù)為一的時候,程序串行執(zhí)行
    [queue setMaxConcurrentOperationCount:1];
    
    
    // 設(shè)置依賴關(guān)系 [A addDependency:B] ,若A依賴B,則B先執(zhí)行,A再執(zhí)行
//    [invocationOperation addDependency:blockOperation];
    
    // A→B→C
    [blockOperation1 addDependency:invocation2];
    [invocation2 addDependency:blockOperation2];
    
    
    // 添加隊(duì)列
//    [queue addOperation:invocationOperation];
//    [queue addOperation:blockOperation];
    [queue addOperation:invocation2];
    [queue addOperation:blockOperation1];
    [queue addOperation:blockOperation2];
}

#pragma mark    - GCD
- (IBAction)gcdAction:(UIButton *)sender {
    NSLog(@"GCD");
    
    // GCD三種隊(duì)列:
        // 主隊(duì)列
        // 全局隊(duì)列
        // 自定義隊(duì)列 (串行隊(duì)列,并行隊(duì)列)
    __weak typeof(self)temp = self;
    
#pragma mark    - 1.主隊(duì)列
    // 1.主隊(duì)列 ※※※※※※
    // 獲取主隊(duì)列生成一個串行的隊(duì)列,隊(duì)列里面的block塊按照FIFO的順序執(zhí)行,實(shí)際上就是一個單線程隊(duì)列
    dispatch_queue_t queue = dispatch_get_main_queue();
        // 往隊(duì)列里面添加任務(wù)
//    dispatch_async(queue, ^{
//        [temp test];
//        NSLog(@"1");
//    });
//    dispatch_async(queue, ^{
//        [temp test];
//        NSLog(@"2");
//    });
//    dispatch_async(queue, ^{
//        [temp test];
//        NSLog(@"3");
//    });
    
    
    // 延時任務(wù)     // ※※※  延遲5秒后觸發(fā). 參數(shù)只需要寫時間
//    dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(5 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
//        
//        NSLog(@"趙哥今晚在如家402等你算數(shù)");
//    });
    
    
    
    
// 這樣很慢, 一般很少用!
//    dispatch_sync(queue, ^{
//        [temp test];
//    });
//
    
    
    
    
    
#pragma mark    - 全局隊(duì)列 (并發(fā)執(zhí)行,隨機(jī)順序執(zhí)行)
    // 2.全局隊(duì)列
//    dispatch_queue_t global = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
    
    // 添加任務(wù)
//    dispatch_async(global, ^{
//        [temp test];
//        NSLog(@"1");
//    });
//     dispatch_async(global, ^{
//         [temp test];
//         NSLog(@"2");
//     });
//    dispatch_async(global, ^{
//        [temp test];
//        NSLog(@"3");
//    });
    
    
    // 重復(fù)執(zhí)行的任務(wù) // 第一個參數(shù):重復(fù)執(zhí)行的次數(shù).  第二個參數(shù):指定執(zhí)行的隊(duì)列. // size_t是個類型, 后面要加上參數(shù)名
//    dispatch_apply(5, global, ^(size_t t) {
//        NSLog(@"執(zhí)行到第%ld次",t);
//    });
    
    
    
    
    
    
    
    
#pragma mark    - 自定義隊(duì)列
    // 3.自定義隊(duì)列
    // 串行隊(duì)列
//    dispatch_queue_t queue1 = dispatch_queue_create("AAA", DISPATCH_QUEUE_SERIAL);
//    dispatch_async(queue1, ^{
//        [temp test];
//        NSLog(@"1");
//    });
//    dispatch_async(queue1, ^{
//        [temp test];
//        NSLog(@"2");
//    });
//    dispatch_async(queue1, ^{
//        [temp test];
//        NSLog(@"3");
//    });
//    
//    
//    // 添加函數(shù) // .._async_f
//    dispatch_async_f(queue1, "testContext", function);
    
    
    
    
    
    
    
    
    // 并行隊(duì)列
    dispatch_queue_t queue2 = dispatch_queue_create("com.baidu", DISPATCH_QUEUE_CONCURRENT);
//    // 障礙執(zhí)行
//    // 該方法創(chuàng)建的任務(wù)在執(zhí)行的時候,會先檢查是否有其他任務(wù)正在執(zhí)行, 若有,等待其執(zhí)行完畢再執(zhí)行,否則其他任務(wù)要等待它執(zhí)行完畢之后再執(zhí)行
//    dispatch_barrier_async(queue2, ^{
//        [temp test];
//        NSLog(@"障礙");
//    });

    
    
    
    
    
    
//    // 分組任務(wù)
//    dispatch_group_t group = dispatch_group_create();
//    // 添加任務(wù)
//    dispatch_group_async(group, queue2, ^{
//        [temp test];
//        NSLog(@"1");
//    });
//    dispatch_group_async(group, queue2, ^{
//        [temp test];
//        NSLog(@"2");
//    });
//    dispatch_group_async(group, queue2, ^{
//        [temp test];
//        NSLog(@"3");
//    });
//    
//    // 最后才會執(zhí)行的方法
//    dispatch_group_notify(group, queue2, ^{
//        NSLog(@"最后,昭哥變成了數(shù)學(xué)家");
//    });
    
    
    
    
    
    
    
    
    
    
    // 購票: 定義并發(fā)隊(duì)列 ,幾個窗口同時搶
    // 模擬購票系統(tǒng)
    dispatch_queue_t queue3 = dispatch_queue_create("CCC", DISPATCH_QUEUE_CONCURRENT);
    // 開始購票:需要添加任務(wù)
    dispatch_async(queue3, ^{
        for (int i = 0; i < 100; i++) {
            [temp buyTicket];
        }
    });
    dispatch_async(queue3, ^{
        for (int i = 0; i < 100; i++) {
            [temp buyTicket];
        }
    });
    
    
    
    
    
    
    
}












-(void)test1{
    NSLog(@"1");
}
-(void)test2{
    NSLog(@"2");
}
-(void)test3{
    NSLog(@"3");
}








// 購票方法
-(void)buyTicket{
    // 自動釋放池 @autoreleasepool
    @autoreleasepool {
        // 加鎖 @synchronized     // 加鎖是因?yàn)楸苊庠斐赡繕?biāo)的搶奪 ************** @synchronized
//            @synchronized(self) {
//            count--;
//            NSLog(@"%d",count);
//        }
        
        
        
        // 用自己定義的鎖來加鎖
        [_lock lock];
        count--;
        NSLog(@"%d",count);
        [_lock unlock];
        
        
    }
}





- (void)didReceiveMemoryWarning {
    [super didReceiveMemoryWarning];
    // Dispose of any resources that can be recreated.
}

@end

之后在Main.storyboard創(chuàng)建五個按鈕,分別是普通計(jì)算, NSObject, NSThread, NSOperationQueue, GCD.

在ViewController.m中分別是下面五個函數(shù),需要自行建立關(guān)系.

  • (IBAction)normalAction:(UIButton *)sender ;// 普通計(jì)算
  • (IBAction)nsobjectAction:(UIButton *)sender ;// NSObject
  • (IBAction)nsthreadAction:(UIButton *)sender ;// NSThread
  • (IBAction)oprerationAction:(UIButton *)sender ;// NSOperationQueue
  • (IBAction)gcdAction:(UIButton *)sender ;// GCD
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容