iOS開發-------多線程的基礎使用方法

實際開發中多線程的使用時非常常見的,多線程是指程序中包含多個執行流,即在一個程序中可以同時運行多個不同的線程來執行不同的任務,也就是說允許單個程序創建多個并行執行的線程來完成各自的任務。可以提高CPU的利用率。在多線程程序中,一個線程必須等待的時候,CPU可以運行其它的線程而不是等待,這樣就大大提高了程序的效率。

本文介紹關于多線程常用的,也是最基本的使用方法。

1.NSObject自帶的多線程

首先創建一個imageView和button:

(文本創建較多按鈕暫時用數字后綴代替,實際編程中盡量避免使用數字)

@property(nonatomic, strong)UIImageView *imageView;
@property(nonatomic, strong)UIButton *button2;

初始化imageView和相應的button:
self.imageView = [[UIImageView alloc] initWithFrame:CGRectMake(107,   
 500, 200, 200)];
 self.imageView.backgroundColor = [UIColor yellowColor];
 [self.view addSubview:self.imageView];

self.button2 = [UIButton buttonWithType:UIButtonTypeCustom];
self.button2.frame = CGRectMake(107, 10 + 40, 200, 30);
self.button2.backgroundColor = [UIColor blueColor];
[self.button2 setTitle:@"自帶的多線程" forState:UIControlStateNormal];
[self.button2 addTarget:self action:@selector(didClickedButton2:) forControlEvents:UIControlEventTouchUpInside];
[self.view addSubview:self.button2];

執行方法
//自帶的多線程
- (void)didClickedButton2:(UIButton *)button2
{
//在多線程里面執行某個方法
[self performSelectorInBackground:@selector(getImageByURL) withObject:nil];

}
//這個方法會在分支線程里執行(非主線程)
- (void)getImageByURL
{
//1.在分支線程里請求數據
self.data = [NSData dataWithContentsOfURL:[NSURL URLWithString:@"http://pic14.nipic.com/20110522/7411759_164157418126_2.jpg"]];
//2.回到主線程更新UI
[self performSelectorOnMainThread:@selector(updataUI) withObject:nil waitUntilDone:YES];
}

//3.回主線程更新UI方法
- (void)updataUI
{
self.imageView.image = [UIImage imageWithData:self.data];
}
B4BB0391-2459-47BA-A5C2-70546A2CE900.png

點擊按鈕

72C6AF07-3489-4186-B162-4A77DC560BBF.png

2.自動分配線程

@property(nonatomic, strong)UIButton *button3;

self.button3 = [UIButton buttonWithType:UIButtonTypeCustom];
self.button3.frame = CGRectMake(107, 10 + 40 + 40, 200, 30);
self.button3.backgroundColor = [UIColor blueColor];
[self.button3 setTitle:@"自動分配" forState:UIControlStateNormal];
[self.button3 addTarget:self action:@selector(didClickedButton3:)   forControlEvents:UIControlEventTouchUpInside];
[self.view addSubview:self.button3];

//自動分配線程
- (void)didClickedButton3:(UIButton *)button3
{
[NSThread detachNewThreadSelector:@selector(getImageByURL) toTarget:self withObject:nil];

}

點擊按鈕


B6237B5D-E059-4241-9224-C9316FCD5D0B.png
832A4853-3703-4180-BDC4-B124A98F884B.png

3.手動分配線程

@property(nonatomic, strong)UIButton *button4;

self.button4 = [UIButton buttonWithType:UIButtonTypeCustom];
self.button4.frame = CGRectMake(107, 10 + 40 + 40 + 40, 200, 30);
self.button4.backgroundColor = [UIColor blueColor];
[self.button4 setTitle:@"手動分配" forState:UIControlStateNormal];
[self.button4 addTarget:self action:@selector(didClickedButton4:) forControlEvents:UIControlEventTouchUpInside];
[self.view addSubview:self.button4];

//手動分配線程
- (void)didClickedButton4:(UIButton *)button4
{
NSThread *thread = [[NSThread alloc] initWithTarget:self selector:@selector(getImageByURL) object:nil];
//手動開啟線程
[thread start];
//讓線程延遲3秒
[NSThread sleepForTimeInterval:3];
}
6CBED177-5C1E-4019-8923-F81FD9DFDC63.png

點擊按鈕視圖會在3秒后呈現


A02A39DC-B9FD-452C-B1BF-5326EFF8CA70.png

4.NSIncationOperation 方法:

按鈕按以上依次創建,這里只寫方法
#pragma mark -- NSIncationOperation 方法:
- (void)didClickedButton5:(UIButton *)button5
{
//這個類是NSOperation的一個子類
NSInvocationOperation *invocationOperation = [[NSInvocationOperation alloc]initWithTarget:self selector:@selector(getImageByURL) object:nil];
//手動開啟
[invocationOperation start];
}
點擊按鈕


C53A3D92-9651-4DBD-A222-EA0C032D7811.png

5.NSBlockOperation方法

pragma mark -- NSBlockOperation方法

- (void)didClickedButton6:(UIButton *)button6
{
__weak ViewController *blockVC = self;
//這個類也是NSOperation的一個子類
NSBlockOperation *blockOperation = [NSBlockOperation blockOperationWithBlock:^{
    //在分支線程里請求數據
    blockVC.data = [NSData dataWithContentsOfURL:[NSURL URLWithString:@"http://pic14.nipic.com/20110522/7411759_164157418126_2.jpg"]];
    
    //回主線程更新UI
    [self performSelectorOnMainThread:@selector(updataUI) withObject:nil waitUntilDone:YES];
}];
//手動開啟
[blockOperation start];
}

點擊按鈕

C329C991-E75E-4043-BBE6-3CF1CCB841B1.png

6.線程隊列

- (void)didClickedButton7:(UIButton *)button7
{
//創建隊列對象
NSOperationQueue *queue = [NSOperationQueue new];
//設置最大并發數
queue.maxConcurrentOperationCount = 1;
//向隊列中添加任務
for (NSInteger i = 0; i < 10; i++) {
    NSBlockOperation *blockOperation = [NSBlockOperation blockOperationWithBlock:^{
        NSLog(@"當前線程 : %@ 是否是主線程:%d : %ld",[NSThread currentThread], [NSThread isMainThread], i );
        
    }];
    //將任務添加到線程隊列中
    [queue addOperation:blockOperation];
}
}

點擊按鈕 打印出:


05F7FF13-B5EE-450E-AEDA-D41BC5F5AC1F.png

7.GCD串行

- (void)didClickedButton8:(UIButton *)button8
{
//方法一:

獲取程序的主隊列:
dispatch_queue_t queue = dispatch_get_main_queue();
dispatch_async(queue, ^{
    NSLog(@"我是第一個任務,是否是主線程:%d",[NSThread isMainThread]);
});
dispatch_async(queue, ^{
    NSLog(@"我是第二個任務,是否是主線程:%d",[NSThread isMainThread]);
});
dispatch_async(queue, ^{
    NSLog(@"我是第三個任務,是否是主線程:%d",[NSThread isMainThread]);
});
dispatch_async(queue, ^{
    NSLog(@"我是第四個任務,是否是主線程:%d",[NSThread isMainThread]);
});
dispatch_async(queue, ^{
    NSLog(@"我是第五個任務,是否是主線程:%d",[NSThread isMainThread]);
});


//方法二:
//創建一個串行隊列
//參數一:隊列的名字(蘋果推薦以反域名的形式書寫)
//參數二:隊列的類型(串行或者并行)
dispatch_queue_t queue = dispatch_queue_create("com.alibaba.queue1", DISPATCH_QUEUE_SERIAL);

dispatch_async(queue, ^{
    NSLog(@"我是第一個任務,是否是主線程:%d",[NSThread isMainThread]);
});
dispatch_async(queue, ^{
    NSLog(@"我是第二個任務,是否是主線程:%d",[NSThread isMainThread]);
});
dispatch_async(queue, ^{
    NSLog(@"我是第三個任務,是否是主線程:%d",[NSThread isMainThread]);
});
dispatch_async(queue, ^{
    NSLog(@"我是第四個任務,是否是主線程:%d",[NSThread isMainThread]);
});
dispatch_async(queue, ^{
    NSLog(@"我是第五個任務,是否是主線程:%d",[NSThread isMainThread]);
});

}

點擊按鈕 打印出:

44675DD5-C101-4FDA-90D3-B3DE86DB17DE.png

8.延時執行

- (void)didClickedButton9:(UIButton *)button9
{
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(3 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
          self.view.backgroundColor = [UIColor redColor];
});
}

點擊按鈕

27B7E06B-600C-4471-8916-1E231C34F096.png

9.只執行一次

- (void)didClickedButton10:(UIButton *)button10
{
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
    NSLog(@"我只走一次");
});

}

點擊按鈕 打印出:

5871839E-24EC-4BC0-A4A7-749DCDDB0A2D.png

10.多次執行

    - (void)didClickedButton11:(UIButton *)button11
{
dispatch_queue_t queue = dispatch_queue_create("com.lanou3g.test", DISPATCH_QUEUE_CONCURRENT);
dispatch_apply(3, queue, ^(size_t index) {
    NSLog(@"我走了 %ld 累死了都 ", index);
});

}

點擊按鈕 打印出:


8175C454-8884-4DC0-ABE5-22D0D222FBB7.png

11.線程互斥

這里舉車站買票例子
- (void)didClickedButton12:(UIButton *)button12
{
self.count = 100; //票的總數
dispatch_queue_t queue = dispatch_queue_create("com.123.6.sellTicket", DISPATCH_QUEUE_CONCURRENT);
//創建線程鎖對象
NSLock *lock = [NSLock new];
//開辟10個買票窗口
for (NSInteger i = 0; i < 10; i++) {
dispatch_async(queue, ^{
[lock lock]; //加鎖

        //每個窗口可以賣10張票
        for (NSInteger j = 0; j < 10; j++) {
            NSLog(@"我買到了第 %ld 張票", self.count);
            self.count--;
            
        }
        [lock unlock]; //解鎖

    });
    
}
}

點擊按鈕 打印出:


23C0C23A-E929-4470-A302-10C3FF2DA01F.png

每個不同按鈕都有各自的方法,感興趣的小伙伴可以試試哦


868D40F4-1BFA-461C-A61B-1253D6CA40A1.png

使用多線程的好處:

可以使CPU多個核同時使用,令計算機效率更高效化,以前單核的機器,同時有兩個線程在運行時,是先把其中某線程先執行的形式,這樣無疑延長了計算所有的時間,多核的情況下,一線程可以交給一個核去處理,另一個線程可以交給另一個核去處理,這個,計算機的資源利用就大大升高.減少用戶等待時間。

什么時候使用多線程:

按生活原理.當你在吃飯的時候看電視,是不是大腦在同時控制你進行著兩種工作?同理,計算機也一樣,比如,軟件在后臺處理文件的時候,同時又顯示給用戶看與后臺處理無關的內容,這時候,我們總不能等后臺處理完了,執行顯示.這時候多線程的優勢就很明顯了.

多線程主要用于計算機同時執行多個任務,而多個任務之間的執行是不互相影響的

希望大家在實際開發中熟練使用多線程,大家一同學習!!!

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容