FMDB多线程读写问题,使用FMDataBaseQueue操作可以解决同时打开一个链接de读写问题
现在ios里使用的数据库一般都是Sqlite,但是使用Sqlite有个不太好的地方就是在多线程的时候,会出现问题,sqlite只能打开一个读或者写连结。这样的话多线程就会碰到资源占用的问题。
最开始是使用FMDB,FMDB的早期版本不能解决这个问题,后来FMDB更新了,新版本的FMDB能够很好的解决这个多线程使用Sqlite 。
FMDB github网址 https://github.com/ccgus/fmdb 最新版的请到github取下载。
本文演示了使用FMDB通过多线程来读和写数据库操作。
1.建立数据库表,我采用的是Firefox的Sqlite manager 来建立的。
建表sql如下
CREATE TABLE "tbl_user" ("_id" INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL , "name" VARCHAR(30), "password" VARCHAR(30))
2. 建立数据表的映射实体UserEntity
#import <Foundation/Foundation.h> @interface UserEntity : NSObject
{
int _id;
NSString *name;
NSString *password;
} @property (nonatomic, assign)int ID;
@property (nonatomic, retain) NSString *name;
@property (nonatomic, retain) NSString *password;
@end
3. 建立操作数据库的dao
//
// DbDao.m
// SqliteTest
//
// Created by foxwang on 12-4-9.
// Copyright (c) 2012年 __MyCompanyName__. All rights reserved.
// #import "DbDao.h"
#import "DbFileManager.h" #import "FMDatabase.h"
#import "FMDatabaseAdditions.h"
#import "FMDatabasePool.h"
#import "FMDatabaseQueue.h"
#import "UserEntity.h" static DbDao *gSharedInstance = nil; @implementation DbDao
@synthesize dbFile;
@synthesize dbQueue; +(DbDao *)sharedInstance
{
@synchronized(self)
{
if (gSharedInstance == nil)
gSharedInstance = [[DbDao alloc] init];
}
return gSharedInstance;
} - (void)dealloc
{
[self.dbFile release];
self.dbQueue = nil;
[super dealloc];
} - (id)init
{
self = [super init];
if (self)
{
self.dbFile = [DbFileManager dbFilePath];
self.dbQueue = [FMDatabaseQueue databaseQueueWithPath:self.dbFile];
}
return self;
} - (UserEntity *)rsToUser:(FMResultSet*)rs
{
UserEntity *user = [[[UserEntity alloc] init] autorelease];
user.ID = [rs intForColumn:@"_id"];
user.name = [rs stringForColumn:@"name"];
user.password = [rs stringForColumn:@"password"];
return user;
} - (void)addUser:(UserEntity *)user
{
[self.dbQueue inTransaction:^(FMDatabase *db, BOOL *rollback) {
[db open];
NSString *sql = @"insert into tbl_user(name, password) values (?, ?)";
[db executeUpdate:sql,user.name, user.password];
[db close];
}];
} - (NSArray *)getUsers;
{
__block NSMutableArray *users = [[[NSMutableArray alloc] init] autorelease];
[self.dbQueue inDatabase:^(FMDatabase *db) {
[db open];
NSString *sql = @"select * from tbl_user ";
FMResultSet *rs = [db executeQuery:sql];
while ([rs next])
{
[users addObject:[self rsToUser :rs]];
}
[db close];
}];
return users;
}
@end
4. 编写测试方法
在didFinishLaunchingWithOptions 方法里启动3个线程 :2个线程写,1个线程读
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
self.window = [[[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]] autorelease];
// Override point for customization after application launch.
self.viewController = [[[ViewController alloc] initWithNibName:@"ViewController" bundle:nil] autorelease];
self.window.rootViewController = self.viewController;
[self.window makeKeyAndVisible];
[NSThread detachNewThreadSelector:@selector(writeDbOne) toTarget:self withObject:nil];
[NSThread detachNewThreadSelector:@selector(readDb) toTarget:self withObject:nil];
[NSThread detachNewThreadSelector:@selector(writeDbTwo) toTarget:self withObject:nil];
return YES;
}
- (void)writeDbOne
{
DbDao *dao = [DbDao sharedInstance];
for (int i = 0; i < 500; i++)
{
@autoreleasepool
{
UserEntity *user = [[[UserEntity alloc] init] autorelease];
user.name = [NSString stringWithFormat:@"name %d", i];
user.password = [NSString stringWithFormat:@"password %d", i];
[dao addUser:user];
NSLog(@"writeDbOne %d ", i);
}
}
} - (void)writeDbTwo
{
DbDao *dao = [DbDao sharedInstance];
for (int i = 600; i < 1200; i++)
{
@autoreleasepool
{
UserEntity *user = [[[UserEntity alloc] init] autorelease];
user.name = [NSString stringWithFormat:@"name %d", i];
user.password = [NSString stringWithFormat:@"password %d", i];
[dao addUser:user];
NSLog(@"writeDbTwo %d ", i);
}
}
} - (void)readDb
{
DbDao *dao = [DbDao sharedInstance];
NSArray *users = [dao getUsers];
NSLog(@"%@", users);
}

最后查看数据库信息,数据成功插入
结论 :使用新的FMDB ,很好的解决了多线程问题
FMDB多线程读写问题,使用FMDataBaseQueue操作可以解决同时打开一个链接de读写问题的更多相关文章
- C#打开一个文本文件并读写
OpenFileDialog OFD = new OpenFileDialog(); OFD.Title = "打开第一个文本文件"; OFD.FileName = "* ...
- Python文件操作:文件的打开关闭读取写入
Python文件操作:文件的打开关闭读取写入 一.文件的打开关闭 Python能以文本和二进制两种方式处理文件,本文主要讨论在Python3中文本文件的操作. 文件操作都分为以下几个步骤: 1.打开文 ...
- 使用FMDB多线程访问数据库,及database is locked的问题
每日更新关注:http://weibo.com/hanjunqiang 新浪微博 今天终于解决了多线程同时访问数据库时,报数据库锁定的问题,错误信息是: Unknown error finalizi ...
- 使用FMDB多线程訪问数据库,及database is locked的问题
今天最终攻克了多线程同一时候訪问数据库时,报数据库锁定的问题.错误信息是: Unknown error finalizing or resetting statement (5: database i ...
- Java入门到精通——基础篇之多线程实现简单的PV操作的进程同步
Java入门到精通——基础篇之多线程实现简单的PV操作的进程同步 一.概述 PV操作是对信号量进行的操作. 进程同步是指在并发进程之间存在一种制约关系,一个进程的执行依赖另一个进程的消 ...
- C#操作Excel(创建、打开、读写、保存)几种方法的总结
在.NET开发中,不管是web程序还是桌面软件(尤其是涉及数据库操作的MIS系统等),常常需操作Excel,如导出数据到Excel,读取Excel中数据到程序中等.总结起来,其操作不外乎创建.打开.读 ...
- QSettings配置读写-win注册表操作-ini文件读写
版权声明:若无来源注明,Techie亮博客文章均为原创. 转载请以链接形式标明本文标题和地址: 本文标题:QSettings配置读写-win注册表操作-ini文件读写 本文地址:http:// ...
- Python基础笔记系列十一:标准输入输出、文件读写和指针等操作
本系列教程供个人学习笔记使用,如果您要浏览可能需要其它编程语言基础(如C语言),why?因为我写得烂啊,只有我自己看得懂!! 标准输入输出一.输入 在sublime中这个时候需要安装SublimeRE ...
- Win8 Metro中文件读写删除与复制操作
Win8Metro中,我们不能在向以前那样调用WIN32的API函数来进行文件操作,因此,下面就来介绍一下Win8 Metro中文件的读写操作. 1 Windows 8 Metro Style App ...
随机推荐
- 【POJ】1451 T9
DFS+字典树. #include <cstdio> #include <cstring> #include <cstdlib> typedef struct Tr ...
- Selenium稳定性 Test
[Test] public void DriverExtension_Wait() { var driver = new FirefoxDriver(); driver.Navigate().GoTo ...
- Win32中文件的操作
1 文件的创建或打开 HANDLE CreateFile( LPCTSTR lpFileName, //文件路径和名称 DWORD dwDesiredAccess, //访问方式,最常用的值 ...
- iOS中懒加载
1.懒加载基本 懒加载——也称为延迟加载,即在需要的时候才加载(效率低,占用内存小).所谓懒加载,写的是其get方法. 注意:如果是懒加载的话则一定要注意先判断是否已经有了,如果没有那么再去进行实例化 ...
- JavaScript 类型判断 —— typeof 以及 instanceof 中的陷阱
JavaScript中基本类型包含Undefined.Null.Boolean.Number.String以及Object引用类型.基本类型可以通过typeof来进行检测,对象类型可以通过instan ...
- STL之deque、queue、stack、list
首先deque和vector是很像的 但是de代表double双向的队列那么deque可以从首部添加(删除)元素也可以从尾部添加(删除)元素. .push_back(elem) .push_front ...
- snatch
https://www.imququ.com/post/use-berserkjs-in-mac.html http://www.one-lab.net/ http://www.oschina.net ...
- Oracle 监控索引使用
Oracle提供一个监控索引的方法,来确定索引是否被使用.如果索引没有被使用,就可以删除它们以减少不必要的语句的开销.因为表上的大量不必要的索引可能会降低DML语句的性能,给数据库性能产生压力.所以生 ...
- Hibernate输出SQL语句以便调试
配置方法:1.打开hibernate.cfg.xml文件编辑界面,在Properties窗口处,点击Add按钮,选择Show_SQL参数,输入值为True. *另外,如果按照同样的步骤,分别加入以下参 ...
- IOS开发中 RunLoop,RunTime
1.Objective-C中的函数调用 对于C语言,函数调用是由编译器直接转化完成的,在编译时程序就开始查找要执行的函数(C语言函数调用原理).而在OC中,我们将函数调用称为消息发送.在编译时程序不查 ...