你好,歡迎來到IOS教程網

 Ios教程網 >> IOS編程開發 >> IOS開發綜合 >> 淺析iOS運用開辟中線程間的通訊與線程平安成績

淺析iOS運用開辟中線程間的通訊與線程平安成績

編輯:IOS開發綜合

線程間的通訊
 
簡略解釋
線程間通訊:在1個過程中,線程常常不是孤立存在的,多個線程之間須要常常停止通訊
 
線程間通訊的表現
1個線程傳遞數據給另1個線程
在1個線程中履行完特定義務後,轉到另1個線程持續履行義務
 
線程間通訊經常使用辦法

- (void)performSelectorOnMainThread:(SEL)aSelector withObject:(id)arg waitUntilDone:(BOOL)wait;
- (void)performSelector:(SEL)aSelector onThread:(NSThread *)thr withObject:(id)arg waitUntilDone:(BOOL)wait;

線程間通訊示例 – 圖片下載

2015111892145343.png (600×346)


//
//  YYViewController.m
//  06-NSThread04-線程間通訊
//
//  Created by apple on 14-6-23.
//  Copyright (c) 2014年 itcase. All rights reserved.
//

#import "YYViewController.h"
@interface YYViewController ()
@property (weak, nonatomic) IBOutlet UIImageView *iconView;
@end


@implementation YYViewController

- (void)viewDidLoad
{
    [super viewDidLoad];
}

-(void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{

// 在子線程中挪用download辦法下載圖片
    [self performSelectorInBackground:@selector(download) withObject:nil];
}

 

-(void)download
{
    //1.依據URL下載圖片
    //從收集中下載圖片
    NSURL *urlstr=[NSURL URLWithString:@"fdsf"];

    //把圖片轉換為二進制的數據
    NSData *data=[NSData dataWithContentsOfURL:urlstr];//這一行操作會比擬耗時

    //把數據轉換成圖片
    UIImage *image=[UIImage imageWithData:data];
 
    //2.回到主線程中設置圖片
    [self performSelectorOnMainThread:@selector(settingImage:) withObject:image waitUntilDone:NO];
}

 

//設置顯示圖片
-(void)settingImage:(UIImage *)image
{
    self.iconView.image=image;
}

@end

代碼2:

//
//  YYViewController.m
//  06-NSThread04-線程間通訊
//
//  Created by apple on 14-6-23.
//  Copyright (c) 2014年 itcase. All rights reserved.
//

#import "YYViewController.h"
#import <NSData.h>

@interface YYViewController ()
@property (weak, nonatomic) IBOutlet UIImageView *iconView;
@end


@implementation YYViewController

- (void)viewDidLoad
{
    [super viewDidLoad];
}

 
-(void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{
// 在子線程中挪用download辦法下載圖片

    [self performSelectorInBackground:@selector(download) withObject:nil];
}

 
-(void)download
{

    //1.依據URL下載圖片
    //從收集中下載圖片
    NSURL *urlstr=[NSURL URLWithString:@"fdsf"];

    //把圖片轉換為二進制的數據
    NSData *data=[NSData dataWithContentsOfURL:urlstr];//這一行操作會比擬耗時

    //把數據轉換成圖片
    UIImage *image=[UIImage imageWithData:data];

    //2.回到主線程中設置圖片
    //第一種方法
//    [self performSelectorOnMainThread:@selector(settingImage:) withObject:image waitUntilDone:NO];

    //第二種方法
    //    [self.imageView performSelector:@selector(setImage:) onThread:[NSThread mainThread] withObject:image waitUntilDone:NO];

    //第三種方法
   [self.iconView performSelectorOnMainThread:@selector(setImage:) withObject:image waitUntilDone:NO];
}


//設置顯示圖片
//-(void)settingImage:(UIImage *)image
//{
//    self.iconView.image=image;
//}

@end

線程平安
 
1、多線程的平安隱患
資本同享
1塊資本能夠會被多個線程同享,也就是多個線程能夠會拜訪統一塊資本
好比多個線程拜訪統一個對象、統一個變量、統一個文件
當多個線程拜訪統一塊資本時,很輕易激發數據紊亂和數據平安成績
示例一:

2015111892251282.png (664×387)

示例二:

2015111892312267.png (659×386)

成績代碼:

//
//  YYViewController.m
//  05-線程平安
//
//  Created by apple on 14-6-23.
//  Copyright (c) 2014年 itcase. All rights reserved.
//


#import "YYViewController.h"

@interface YYViewController ()
//殘剩票數

@property(nonatomic,assign) int leftTicketsCount;
@property(nonatomic,strong)NSThread *thread1;
@property(nonatomic,strong)NSThread *thread2;
@property(nonatomic,strong)NSThread *thread3;


@end


@implementation YYViewController


- (void)viewDidLoad
{
    [super viewDidLoad];

    //默許有20張票

    self.leftTicketsCount=10;

    //開啟多個線程,模仿售票員售票

    self.thread1=[[NSThread alloc]initWithtarget:self selector:@selector(sellTickets) object:nil];

    self.thread1.name=@"售票員A";

    self.thread2=[[NSThread alloc]initWithtarget:self selector:@selector(sellTickets) object:nil];

    self.thread2.name=@"售票員B";

    self.thread3=[[NSThread alloc]initWithtarget:self selector:@selector(sellTickets) object:nil];
    self.thread3.name=@"售票員C";
}

 
-(void)sellTickets
{
    while (1) {
        //1.先檢討票數
        int count=self.leftTicketsCount;
        if (count>0) {
            //暫停一段時光
            [NSThread sleepForTimeInterval:0.002];

            //2.票數-1
           self.leftTicketsCount= count-1;
 
            //獲得以後線程
            NSThread *current=[NSThread currentThread];
            NSLog(@"%@--賣了一張票,還殘剩%d張票",current,self.leftTicketsCount);
        }else
        {
            //加入線程
            [NSThread exit];
        }
    }
}


-(void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{
    //開啟線程

   [self.thread1 start];
    [self.thread2 start];
    [self.thread3 start];

}

@end

打印成果:

2015111892340617.png (871×448)

2、平安隱患剖析

https://www.ios5.online/ios/UploadFiles_8070/201703/2017031615452734.png (625×320)

2015111892430149.png (678×379)

3、若何處理
 
互斥鎖應用格局
@synchronized(鎖對象) { // 須要鎖定的代碼  }
留意:鎖定1份代碼只用1把鎖,用多把鎖是有效的
 
代碼示例:

//
//  YYViewController.m
//  05-線程平安
//
//  Created by apple on 14-6-23.
//  Copyright (c) 2014年 itcase. All rights reserved.
//

#import "YYViewController.h"

@interface YYViewController ()

//殘剩票數
@property(nonatomic,assign) int leftTicketsCount;
@property(nonatomic,strong)NSThread *thread1;
@property(nonatomic,strong)NSThread *thread2;
@property(nonatomic,strong)NSThread *thread3;
@end

@implementation YYViewController

- (void)viewDidLoad
{
    [super viewDidLoad];
    //默許有20張票
    self.leftTicketsCount=10;
    //開啟多個線程,模仿售票員售票

    self.thread1=[[NSThread alloc]initWithTarget:self selector:@selector(sellTickets) object:nil];

    self.thread1.name=@"售票員A";

    self.thread2=[[NSThread alloc]initWithTarget:self selector:@selector(sellTickets) object:nil];

    self.thread2.name=@"售票員B";

    self.thread3=[[NSThread alloc]initWithTarget:self selector:@selector(sellTickets) object:nil];

    self.thread3.name=@"售票員C";
}


-(void)sellTickets
{
    while (1) {
        @synchronized(self){//只能加一把鎖
        //1.先檢討票數

        int count=self.leftTicketsCount;
        if (count>0) {
            //暫停一段時光
            [NSThread sleepForTimeInterval:0.002];
            //2.票數-1

           self.leftTicketsCount= count-1;
            //獲得以後線程
            NSThread *current=[NSThread currentThread];
            NSLog(@"%@--賣了一張票,還殘剩%d張票",current,self.leftTicketsCount);

        }else
        {
            //加入線程
            [NSThread exit];
        }
        }
    }
}


-(void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{

    //開啟線程
   [self.thread1 start];
    [self.thread2 start];
    [self.thread3 start];
}

@end

履行後果圖

https://www.ios5.online/ios/UploadFiles_8070/201703/2017031615452858.png (876×191)

互斥鎖的優缺陷
長處:能有用避免因多線程掠奪資本形成的數據平安成績
缺陷:須要消費年夜量的CPU資本
 
互斥鎖的應用條件:多條線程掠奪統一塊資本
相干專業術語:線程同步,多條線程按次序地履行義務
互斥鎖,就是應用了線程同步技巧
 
四:原子和非原子屬性
 
OC在界說屬性時有nonatomic和atomic兩種選擇
atomic:原子屬性,為setter辦法加鎖(默許就是atomic)
nonatomic:非原子屬性,不會為setter辦法加鎖
 
atomic加鎖道理

@property (assign, atomic) int age;

- (void)setAge:(int)age
{

    @synchronized(self) {
       _age = age;
    }
}

原子和非原子屬性的選擇
nonatomic和atomic比較

  • atomic:線程平安,須要消費年夜量的資本
  • nonatomic:非線程平安,合適內存小的挪動裝備 

IOS開辟的建議

  • 一切屬性都聲明為nonatomic
  • 盡可能防止多線程掠奪統一塊資本
  • 盡可能將加鎖、資本掠奪的營業邏輯交給辦事器端處置,減小挪動客戶真個壓力

【淺析iOS運用開辟中線程間的通訊與線程平安成績】的相關資料介紹到這裡,希望對您有所幫助! 提示:不會對讀者因本文所帶來的任何損失負責。如果您支持就請把本站添加至收藏夾哦!

  1. 上一頁:
  2. 下一頁:
蘋果刷機越獄教程| IOS教程問題解答| IOS技巧綜合| IOS7技巧| IOS8教程
Copyright © Ios教程網 All Rights Reserved