executeBlock 和 scheduleBlock 方法应用场景分析
开源代码:
- (void)executeBlock:(dispatch_block_t)block
{
// By design this method should not be invoked from the storageQueue.
//
// If you remove the assert statement below, you are destroying the sole purpose for this class,
// which is to optimize the disk IO by buffering save operations.
//
NSAssert(dispatch_get_specific((__bridge void *)self) != maybe_bridge(storageQueue), @"Invoked on incorrect queue");
//
// For a full discussion of this method, please see XMPPCoreDataStorageProtocol.h
//
// dispatch_Sync
// ^
OSAtomicIncrement32(&pendingRequests);
dispatch_sync(storageQueue, ^{
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
block();
// Since this is a synchronous request, we want to return as quickly as possible.
// So we delay the maybeSave operation til later.
dispatch_async(storageQueue, ^{
NSAutoreleasePool *innerPool = [[NSAutoreleasePool alloc] init];
[self maybeSave:OSAtomicDecrement32(&pendingRequests)];
[innerPool drain];
});
[pool drain];
});
}
- (void)scheduleBlock:(dispatch_block_t)block
{
// By design this method should not be invoked from the storageQueue.
//
// If you remove the assert statement below, you are destroying the sole purpose for this class,
// which is to optimize the disk IO by buffering save operations.
//
NSAssert(dispatch_get_specific((__bridge void *)self) != maybe_bridge(storageQueue), @"Invoked on incorrect queue");
//
// For a full discussion of this method, please see XMPPCoreDataStorageProtocol.h
//
// dispatch_Async
// ^
OSAtomicIncrement32(&pendingRequests);
dispatch_async(storageQueue, ^{
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
block();
[self maybeSave:OSAtomicDecrement32(&pendingRequests)];
[pool drain];
});
}
- (void)maybeSave:(int32_t)currentPendingRequests
{
NSAssert(dispatch_get_specific((__bridge void *)self) == maybe_bridge(storageQueue), @"Invoked on incorrect queue");
if ([[self managedObjectContext] hasChanges])
{
if (currentPendingRequests == 0)
{
[self save];
}
else
{
NSUInteger unsavedCount = [self numberOfUnsavedChanges];
if (unsavedCount >= saveThreshold)
{
[self save];
}
}
}
}
- (NSUInteger)numberOfUnsavedChanges
{
NSManagedObjectContext *moc = [self managedObjectContext];
NSUInteger unsavedCount = 0;
unsavedCount += [[moc updatedObjects] count];
unsavedCount += [[moc insertedObjects] count];
unsavedCount += [[moc deletedObjects] count];
return unsavedCount;
}
executeBlock 和 scheduleBlock 方法应用场景分析:
通过代码可以看出
两个方法相同之处:
scheduleBlock 和 executeBlock 完全是使用maybesave提高了数据库的效率.(数据库里的maybesave方法在一定程度上减少了数据库的频繁操作。)。并且maybesave 方法都是在异步线程里操作的。
两个方法不同之处:
scheduleBlock 执行的block的线程是子线程, 而executeBlock执行block的线程是主线程, 这在效率上肯定是scheduleBlock效率高。
所以最大的不同在于我们写的增删改查的代码是在主线程执行还是子线程执行。
为此得出应用场景结论:
对于数据库插入(更新)后过一段时间才会使用到插入或者跟新的数据, 一般使用scheduleBlock
对于数据库插入(更新)后 及时使用数据库的数据,其实使用scheduleBlock和executeBlock都会存在问题,(可能
数据没有插入,你可能就开始取数据了,这时候必须在block里提前调用一下save操作)
至于OSAtomicIncrement32 和 OSAtomicDecrement32 这俩其实就是简单的++ 和—-
这种++ 和 — 和 a=a+1 a=a-1不同之处, 在于在原子操作的粒度上相当于一个锁,保障了原子操作
的安全性, 理解原子操作,需要理解操作系统的地址总线,大家可以自己百度谷歌。(我们的数据库executeBlock和
scheduleBlock其实都是在主线程里调用的,没有在子线程里调用,其实对于我们这原子操作的意义也不大)