上一节中,我转载他人的文章,对多线程的理论知识进行了大致的描述,如果想了解的话,请点击这里。接下来的几节内容,我将一一介绍各自的使用。
1. NSThread相关的主要方法:
创建、启动线程
NSThread *thread = [[NSThread alloc] initWithTarget:self selector:@selector(run) object:nil]; [thread start]; // 线程一启动,就会在线程thread中执行self的run方法
- (BOOL)isMainThread; // 是否为主线程 + (BOOL)isMainThread; // 是否为主线程
NSThread *current = [NSThread currentThread]; - (void)setName:(NSString *)name; - (NSString *)name;
创建线程后自动启动线程
[NSThread detachNewThreadSelector:@selector(run) toTarget:self withObject:nil];
[self performSelectorInBackground:@selector(run) withObject:nil];
3. 互斥锁
@synchronized(锁对象) { // 需要锁定的代码 }
注意:锁定1份代码只用1把锁,用多把锁是无效的
@property (assign, atomic) int age;
- (void)setAge:(int)age
{
@synchronized(self) {
_age = age;
}
}
什么叫做线程间通信
- (void)performSelectorOnMainThread:(SEL)aSelector withObject:(id)arg waitUntilDone:(BOOL)wait; - (void)performSelector:(SEL)aSelector onThread:(NSThread *)thr withObject:(id)arg waitUntilDone:(BOOL)wait;
6. Demo 演示
业务描述(卖票): 模拟两个线程抢夺一份资源
运行结果图:
主要代码说明:
1. 属性及方法定义:
/*
1. NSThread 可以使用NSLock 进行加锁工作
2. NSOperation和GCD 应该使用同步锁 :@synchronized(self),并且抢夺的内存资源应该定义为 atomic 的属性
*/
@property (atomic,assign) int tickets;
@property (atomic,strong) NSLock *lock;
// 显示结果区域
@property (weak, nonatomic) IBOutlet UITextView *messageBoard;
// 开始售票
- (IBAction)threadSale;
- (IBAction)threadSale {
// 1. 先设定销售票的数量
_tickets = 100;
// 创建线程1
NSThread *thread1 = [[NSThread alloc]initWithTarget:self selector:@selector(threadSaleMethod) object:nil];
// 便于跟踪时知道谁在工作
thread1.name = @"售票线程-1";
// 启动线程
[thread1 start];
// 创建线程2
NSThread *thread2 = [[NSThread alloc]initWithTarget:self selector:@selector(threadSaleMethod) object:nil];
thread2.name = @"售票线程-2";
[thread2 start];
}
- (void)threadSaleMethod {
// 1. 定义锁,懒加载
if (_lock == nil) {
_lock = [[NSLock alloc] init];
}
while(YES)
{
[_lock lock];
if(_tickets > 0)
{
NSString *message = [NSString stringWithFormat:@"当前票数是%d,售票线程是%@",_tickets,[[NSThread currentThread] name]];
// 更新UI的工作,一定要放在主线程中完成
// waitUntilDone 的意思是:是否等待主线程更新完毕
[self performSelectorOnMainThread:@selector(appendTextView:) withObject:message waitUntilDone:YES];
_tickets--;
// 当前线程执行完毕,解锁
[_lock unlock];
// 模拟延时
if ([[[NSThread currentThread] name] isEqualToString:@"售票线程-1"]) {
[NSThread sleepForTimeInterval:0.2];
} else {
[NSThread sleepForTimeInterval:0.3];
}
}
else{
// 在退出之前需要解锁
[_lock unlock];
// 结束信息
NSString *str = [NSString stringWithFormat:@"票已售完%@", [[NSThread currentThread] name]];
[self performSelectorOnMainThread:@selector(appendTextView:) withObject:str waitUntilDone:YES];
break;
}
}
}
- (void)appendTextView:(NSString *)text {
NSMutableString *str = [NSMutableString stringWithString:self.messageBoard.text];
[str appendFormat:@"\n%@", text];
self.messageBoard.text = str;
// 用来将文本框滚动到想要的位置
// 我们现在想要滚动到最后,这个方法的参数是一个NSRange
NSRange range = NSMakeRange(str.length, 1);
[self.messageBoard scrollRangeToVisible:range];
}原文:http://blog.csdn.net/sinat_27706697/article/details/45618199