- (void)viewDidLoad {
[super viewDidLoad];
self.lock = [[NSObject alloc]init];
//设置总票数
self.totalCount = 100;
//初始化售票员(创建线程对象)
self.thread01 = [[NSThread alloc]initWithTarget:self selector:@selector(saleTicket) object:nil];
self.thread02 = [[NSThread alloc]initWithTarget:self selector:@selector(saleTicket) object:nil];
self.thread03 = [[NSThread alloc]initWithTarget:self selector:@selector(saleTicket) object:nil];
//设置名称
self.thread01.name = @"售票员小妹A";
self.thread02.name = @"售票员小妹B";
self.thread03.name = @"售票员小妹C";
//启动线程
[self.thread01 start];
[self.thread02 start];
[self.thread03 start];
}
-(void)saleTicket {
while (1) {
//为代码添加同步锁(互斥锁)
/*
* token:锁对象 (要使用全局的对象) 建议直接使用self
* {} 要加锁的代码段
* 注意点:①加多把锁是无效的②要注意加锁的位置
*/
//线程A
//线程C (排队)
//线程B 如果锁对象是状态是关闭的,那么线程B进入阻塞状态(等待)
//当锁打开之后,会主动唤醒排队的线程(B)
@synchronized(self) {
//售票 检查余票-如果有票卖出一张,否则提示用户
NSInteger count = self.totalCount;
if (count >0) {
//卖票
self.totalCount = count - 1;
for (int i = 0; i < 10000000; ++i) {
}
NSLog(@"%@卖出去了一张票,还剩下%zd张票",[NSThread currentThread].name,self.totalCount);
} else {
//提示用户票已经卖完
NSLog(@"%@发现票已经卖完啦",[NSThread currentThread].name);
break;
}
}
}
}
@end
在开发中,多线程抢夺资源的情况并不多,定义属性的时候不写,默认是原子属性的
#import "ViewController.h"
@interface ViewController ()
@property (weak, nonatomic) IBOutlet UIImageView *imageView;
@end
@implementation ViewController
/*
App Transport Security Settings
Allow Arbitrary Loads YES -- 这么设置就允许发送http请求
*/
#pragma mark -----------------------
#pragma mark Events
-(void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event
{
//创建子线程(3种方法)
[NSThread detachNewThreadSelector:@selector(download) toTarget:self withObject:nil];
}
#pragma mark -----------------------
#pragma mark Methods
-(void)download {
NSLog(@"download----%@",[NSThread currentThread]);
//01 确定URL地址
NSURL *url = [NSURL URLWithString:@"http://image.tianjimedia.com/uploadImages/2015/083/30/VVJ04M7P71W2.jpg"];
//02 把图片的二进制数据下载到本地
NSData *imageData = [NSData dataWithContentsOfURL:url];
//03 把图片的二进制格式转换为UIimage
UIImage *image = [UIImage imageWithData:imageData];
//报错:把和UI相关的操作放在后台线程中处理
//04 回到主线程显示图片
//子线程切换回主线程
/* 参数说明
*
* 第一个参数:方法选择器 回到主线程要做什么(方法)
* 第二个参数:调用函数需要传递的参数
* 第三个参数:是否等待该方法(方法选择器的方法)执行完毕才继续往下执行 YES:等待
*/
//第一种方法
//[self performSelectorOnMainThread:@selector(showImage:) withObject:image waitUntilDone:YES];
//第二种方法
[self performSelector:@selector(showImage:) onThread:[NSThread mainThread] withObject:image waitUntilDone:YES];
//简便方法
//[self.imageView performSelectorOnMainThread:@selector(setImage:) withObject:image waitUntilDone:YES];
NSLog(@"_____end______");
}
-(void)showImage:(UIImage *)image {
//NSLog(@"UI----%@",[NSThread currentThread]);
for (int i = 0; i < 100; ++i) {
NSLog(@"%zd---",i);
}
self.imageView.image = image;
}
#pragma mark -----------------------
#pragma mark 计算代码段执行时间的两种方法
-(void)timer {
NSDate *start = [NSDate date]; //获得当前的时间
//01 确定URL地址
NSURL *url = [NSURL URLWithString:@"http://image.tianjimedia.com/uploadImages/2015/083/30/VVJ04M7P71W2.jpg"];
NSDate *end = [NSDate date]; //获得当前的时间
NSLog(@"%f",[end timeIntervalSinceDate:start]);
//02 把图片的二进制数据下载到本地
NSData *imageData = [NSData dataWithContentsOfURL:url];
//03 把图片的二进制格式转换为UIimage
UIImage *image = [UIImage imageWithData:imageData];
//04 显示图片
self.imageView.image = image;
}
-(void)timer2 {
CFTimeInterval start = CFAbsoluteTimeGetCurrent();//获得当前时间(相对时间)
//01 确定URL地址
NSURL *url = [NSURL URLWithString:@"http://image.tianjimedia.com/uploadImages/2015/083/30/VVJ04M7P71W2.jpg"];
CFTimeInterval end = CFAbsoluteTimeGetCurrent();//获得当前时间(相对时间)
NSLog(@"%f",end - start);
//02 把图片的二进制数据下载到本地
NSData *imageData = [NSData dataWithContentsOfURL:url];
//03 把图片的二进制格式转换为UIimage
UIImage *image = [UIImage imageWithData:imageData];
//04 显示图片
self.imageView.image = image;
}
@end