上一节中,我转载他人的文章,对多线程的理论知识进行了大致的描述,如果想了解的话,请点击这里。接下来的几节内容,我将一一介绍各自的使用。
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