面试题答案
一键面试1. 线程安全问题
- 资源竞争:多个线程同时访问和修改JSON解析和模型转换过程中的共享资源,如临时数据结构、缓存等,可能导致数据不一致。例如,一个线程正在写入解析后的模型数据,另一个线程同时读取,可能读到不完整的数据。
- 重复解析:不同线程可能重复对相同的JSON数据进行解析,浪费系统资源。
- 锁争用:如果使用锁机制来保证线程安全,可能会出现锁争用问题,导致性能下降。多个线程频繁竞争锁,会使线程等待时间增加,降低整体效率。
2. 确保线程安全的机制
- 队列串行化:
- 使用
NSOperationQueue
或DispatchQueue
将JSON解析与模型转换任务串行化。例如,使用DispatchQueue
的serial
队列:
- 使用
static dispatch_queue_t jsonParseQueue;
@implementation YourClass
+ (void)initialize {
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
jsonParseQueue = dispatch_queue_create("com.yourcompany.jsonparse", DISPATCH_QUEUE_SERIAL);
});
}
- (void)parseJSONAndConvertToModel:(NSData *)jsonData {
dispatch_async(jsonParseQueue, ^{
NSError *error;
id jsonObject = [NSJSONSerialization JSONObjectWithData:jsonData options:0 error:&error];
if (error) {
// 异常处理
[self handleJSONError:error];
return;
}
// 模型转换逻辑
id model = [self convertJSONToModel:jsonObject];
if (!model) {
// 模型转换异常处理
[self handleModelConversionError];
}
});
}
@end
- 线程局部存储:使用
pthread_key_t
创建线程局部存储,每个线程有自己独立的临时数据空间,避免资源竞争。不过在Objective-C中,这种方式相对复杂,一般优先使用DispatchQueue
。 - 只读数据共享:对于一些不需要修改的共享数据(如JSON解析器的配置信息),可以让多个线程安全地共享,提高效率。例如,
NSJSONReadingOptions
可以在多个线程中共享,因为它是只读的。
3. JSON数据格式异常处理
- 字段验证:在模型转换过程中,对每个字段进行验证。例如,假设我们有一个
User
模型,有name
(字符串类型)和age
(整型)字段:
@interface User : NSObject
@property (nonatomic, strong) NSString *name;
@property (nonatomic, assign) NSInteger age;
+ (instancetype)userWithJSON:(NSDictionary *)json;
@end
@implementation User
+ (instancetype)userWithJSON:(NSDictionary *)json {
User *user = [[User alloc] init];
id nameValue = json[@"name"];
if (![nameValue isKindOfClass:[NSString class]]) {
// 处理name字段类型不匹配
[self handleFieldTypeError:@"name" expectedType:@"NSString"];
return nil;
}
user.name = nameValue;
id ageValue = json[@"age"];
if (![ageValue isKindOfClass:[NSNumber class]]) {
// 处理age字段类型不匹配
[self handleFieldTypeError:@"age" expectedType:@"NSNumber"];
return nil;
}
user.age = [ageValue integerValue];
return user;
}
+ (void)handleFieldTypeError:(NSString *)fieldName expectedType:(NSString *)expectedType {
NSLog(@"Field %@ has wrong type. Expected %@", fieldName, expectedType);
// 可以在这里进行更复杂的处理,如上报错误等
}
@end
- 异常捕获与恢复:在解析和转换过程中使用
@try
@catch
块捕获异常,确保程序不会崩溃。例如:
- (void)parseJSONAndConvertToModel:(NSData *)jsonData {
dispatch_async(jsonParseQueue, ^{
@try {
NSError *error;
id jsonObject = [NSJSONSerialization JSONObjectWithData:jsonData options:0 error:&error];
if (error) {
[self handleJSONError:error];
return;
}
id model = [self convertJSONToModel:jsonObject];
if (!model) {
[self handleModelConversionError];
}
} @catch (NSException *exception) {
NSLog(@"Caught exception: %@", exception);
// 可以进行异常上报等操作
}
});
}
通过以上方案,可以在多线程环境下保证JSON解析与模型转换的线程安全,并优雅处理JSON数据格式异常,提升程序的稳定性和健壮性。