1.线程和进程的区别?
总的来说一个进程有多个线程
进程有独立的地址空间,一个进程崩溃后,在保护模式的影响下不会对其他进程产生影响,而线程只是一个进程中的不同执行路径。线程有自己的堆栈和局部变量,但线程之间没有单独的地址空间,一个线程死掉就等同于整个进程死掉,所以多进程的程序要比多线程的程序健壮,但在进程切换时,耗费资源较大,效率要差一些。但对于一些要求同时进行并且又要共享某些变量的并发操作,只能用线程,不能用进程。
2.队列、同步异步
1.有多少种队列?
- 串行队列
dispatch_queue_create("com.starming.serialqueue", DISPATCH_QUEUE_SERIAL)
一个任务执行完成,在执行下一个任务
- 并行队列
dispatch_queue_create("com.starming.concurrentqueue", DISPATCH_QUEUE_CONCURRENT)
并发执行,而且无法确定任务的执行顺序
- 全局队列
dispatch_get_global_queue
全局队列也是并行队列
- 主队列
dispatch_get_main_queue
每一个应用程序只有一个主线程即只有一个主队列
2.同步、异步的区别
同步、异步:是否具备开启新线程的能力
同步:dispatch_sync
异步:dispatch_async
3.几种多线程的表示方法?
- NSThread
需要启动线程,线程执行的优先级可以设置,最高为1 - NSOperation
- GCD
1.dispatch_after 延后执行
dispatch_after只是延时提交block,不是延时立刻执行。
double delayInSeconds = 2.0;
dispatch_time_t popTime = dispatch_time(DISPATCH_TIME_NOW, (int64_t) (delayInSeconds * NSEC_PER_SEC));
dispatch_after(popTime, dispatch_get_main_queue(), ^(void){
[self bar];
});
2.dispatch_once 只执行一次
dispatch_once_t要是全局或static变量,保证dispatch_once_t只有一份实例
+ (UIColor *)boringColor;
{
static UIColor *color;
//只运行一次
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
color = [UIColor colorWithRed:0.380f green:0.376f blue:0.376f alpha:1.000f];
});
return color;
}
3.Dispatch_groups
dispatch groups是专门用来监视多个异步任务。dispatch_group_t实例用来追踪不同队列中的不同任务。
当group里所有事件都完成GCD API有两种方式发送通知,第一种是dispatch_group_wait,会阻塞当前进程,等所有任务都完成或等待超时。第二种方法是使用dispatch_group_notify,异步执行闭包,不会阻塞。
dispatch_queue_t concurrentQueue = dispatch_queue_create("com.starming.gcddemo.concurrentqueue",DISPATCH_QUEUE_CONCURRENT);
dispatch_group_t group = dispatch_group_create();
//在group中添加队列的block
dispatch_group_async(group, concurrentQueue, ^{
[NSThread sleepForTimeInterval:2.f];
NSLog(@"1");
});
dispatch_group_async(group, concurrentQueue, ^{
NSLog(@"2");
});
dispatch_group_wait(group, DISPATCH_TIME_FOREVER);
NSLog(@"go on");
4.线程锁
在上锁和开锁之间的这个段代码只能单个线程进行访问,只有当一个线程运行到开锁之后,另一个线程才可以进入。这个操作也可以称为线程同步。
这一块常用的锁有:NSLock、synchornized、NSCondition
FMDB如何使用dispatch_queue_set_specific和dispatch_get_specific来防止死锁
static const void * const kDispatchQueueSpecificKey = &kDispatchQueueSpecificKey;
//创建串行队列,所有数据库的操作都在这个队列里
_queue = dispatch_queue_create([[NSString stringWithFormat:@"fmdb.%@", self] UTF8String], NULL);
//标记队列
dispatch_queue_set_specific(_queue, kDispatchQueueSpecificKey, (__bridge void *)self, NULL);
//检查是否是同一个队列来避免死锁的方法
- (void)inDatabase:(void (^)(FMDatabase *db))block {
FMDatabaseQueue *currentSyncQueue = (__bridge id)dispatch_get_specific(kDispatchQueueSpecificKey);
assert(currentSyncQueue != self && "inDatabase: was called reentrantly on the same queue, which would lead to a deadlock");
}
网友评论