線程間的通訊
簡略解釋
線程間通訊:在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;
線程間通訊示例 – 圖片下載
//
// 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塊資本能夠會被多個線程同享,也就是多個線程能夠會拜訪統一塊資本
好比多個線程拜訪統一個對象、統一個變量、統一個文件
當多個線程拜訪統一塊資本時,很輕易激發數據紊亂和數據平安成績
示例一:
示例二:
成績代碼:
//
// 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
打印成果:
2、平安隱患剖析
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
履行後果圖
互斥鎖的優缺陷
長處:能有用避免因多線程掠奪資本形成的數據平安成績
缺陷:須要消費年夜量的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比較
IOS開辟的建議
【淺析iOS運用開辟中線程間的通訊與線程平安成績】的相關資料介紹到這裡,希望對您有所幫助! 提示:不會對讀者因本文所帶來的任何損失負責。如果您支持就請把本站添加至收藏夾哦!