• IOS多线程读写Sqlite问题解决


    现在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 ,很好的解决了多线程问题。 

     项目文件下载

    团结就是力量,ios开发者自己的推广联盟 QQ群173063969  
  • 相关阅读:
    洛谷 P1823 音乐会的等待
    [The Diary] 10.30 Monday
    洛谷 P1094 纪念品分组
    codevs 1258 关路灯
    NOIP 2012 国王游戏(60分)
    bzoj3745 [COCI2015]Norma
    CF1110E Magic Stones
    bzoj4237 稻草人
    bzoj2653 middle
    单调队列与斜率优化杂题
  • 原文地址:https://www.cnblogs.com/likwo/p/2438790.html
Copyright © 2020-2023  润新知