一.使用NSPort进行线程间的通讯(端口和套接字来实现线程间通讯)
NSPort
对象必须添加到要接收消息的线程的Runloop
中- 接收消息的对象实现
NSPortDelegate
协议的-handlePortMessage:
方法来获取消息内容
代码中首先将self.mainPort
添加到主线程的Runloop
中,然后起新线程下载头像,下载完成后通过mainPort
发送消息,此时并没有手动切换线程,但是controller
中的回调却是在主线程中的,如此便完成了线程间的通讯。
self.mainPort = [[NSMachPort alloc]init];
// self.mainPort.delegate = self;
NSMutableArray *components = @[data].mutableCopy;
[self.port sendBeforeDate:[NSDate date] msgid:1 components:components from:self.downloaderPort reserved:0];
//代理方法
-(void)handlePortMessage:(NSPortMessage *)message{
NSLog(@"handlePortMessage: %@", [NSThread currentThread]);
NSArray *array = [(id)message valueForKey:@"components"];
NSData *data = array[0];
UIImage *avatar = [UIImage imageWithData:data];
imgv.image = avatar;
NSData *responseMsg = [@"附带的信息" dataUsingEncoding:NSUTF8StringEncoding];
NSMutableArray *components = @[responseMsg].mutableCopy;
NSPort *remotePort = [(id)message valueForKey:@"remotePort"];
// downloader线程已销毁,因此要给remotePort发消息,就得把它添加到存活的runloop中
[[NSRunLoop currentRunLoop] addPort:remotePort forMode:NSDefaultRunLoopMode];
[remotePort sendBeforeDate:[NSDate date] msgid:2 components:components from:self.mainPort reserved:0];
}
三:NSCondition
// 生产者-消费者模式
// 线程1
// 删除数组中的元素
- (void)__remove
{
[self.condition lock];
if (self.data.count == 0) {
// 等待
[self.condition wait];
}
[self.data removeLastObject];
[self.condition unlock];
}
// 线程2
// 往数组中添加元素
- (void)__add
{
[self.condition lock];
[self.data addObject:@"Test"];
// 信号
[self.condition signal];
// 广播
//[self.condition broadcast];
[self.condition unlock];
}
二:NSConditionLock 条件锁,是对NSCondition的进一步封装
当使用条件锁使一个线程等待(wait
)时,该线程会被阻塞并进入休眠状态,在另一个线程中对同一个条件锁发送信号(single
),则等待中的线程会被唤醒继续执行任务
//构建条件锁,条件值为1
NSConditionLock *lock = [[NSConditionLock alloc]initWithCondition:1];
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
//线程1 传入9,与条件值不相等,无法正确进行加锁操作,会阻塞线程
[lock lockWhenCondition:9];
NSLog(@"11111");
sleep(1);
[lock unlock];
});
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
sleep(1);
//传入1,如果与条件的值相等,返回YES;如果不相等则返回NO; 不会阻塞当前线程
if ([lock tryLockWhenCondition:1]) {
NSLog(@"22222");
NSLog(@"2加锁");
//解锁,并把条件值修改为9
[lock unlockWithCondition:9];
// [lock unlock];
}else{
NSLog(@"2加锁失败");
}
});