天天看點

NSCondition 多線程解決生産者消費者問題

<pre name="code" class="objc">#import "ViewController.h"

@interface ViewController ()
//資料緩沖區
@property (strong, nonatomic) NSMutableArray *products;
//線程鎖
@property (strong, nonatomic) NSCondition *condition;

/*
 使用NSCondition能夠解決線程的生産者消費者問題
 基本思路是,首先建立NSCondition執行個體,然後消費者取得鎖,取産品,如果沒有,則wait,這時會釋放鎖,直到有線程喚醒它去消費,最後unlock;
 生産者制造産品,首先也是取得鎖,然後生産,在發signal,這樣可以喚醒wait的消費線程
 */

@end

@implementation ViewController

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


-(void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event
{
    NSLog(@"開始生産者消費者模式");
    //建立一個生産者
    [NSThread detachNewThreadSelector:@selector(createProducer) toTarget:self withObject:nil];
    
    //建立三個消費者
    for (int i=0; i<3; i++) {
        NSThread *thread = [[NSThread alloc]initWithTarget:self selector:@selector(createConsuser) object:nil];
        thread.name = [NSString stringWithFormat:@"第%d個消費者",i];
        [thread start];
    }
    
}
//生産資料
-(void)createProducer{
    for (int i = 0; i<9; i++) {
        [NSThread sleepForTimeInterval:1.0];
        NSObject *cai = [[NSObject alloc]init];
        [self.products addObject:cai];
        NSLog(@"生産了一個菜");
        //此方法能夠喚醒一個等待中的線程,如果有多個線程在等待,随機喚醒一個
        [self.condition signal];
    }
}
//消費資料
-(void)createConsuser{
    for (int i=0; i<3; i++)
    {
        [self.condition lock];
        [self.condition wait];
        [self.condition unlock];
        [self.products removeObjectAtIndex:0];
        NSLog(@"%@端走一個菜",[NSThread currentThread].name);
    }
}

- (NSMutableArray *)products
{
    if (!_products)
    {
        _products = [NSMutableArray new];
        
    }
    return _products;
}

- (NSCondition *)condition
{
    if (!_condition)
    {
        _condition = [NSCondition new];
    }
    return _condition;
}
@end