亚洲欧美日韩综合系列在线_91精品人妻一区二区_欧美大肥婆一级特大AA片_九色91视频免费观看_亚洲综合国产精品_av中文字幕在线不卡_久久精品色综合网_看黄色视频的软件_无卡无码高清中文字幕码2024_亚洲欧美日韩天堂网

Android數(shù)據(jù)庫并發(fā)操作解決思路

來源: lizhengwei1989 發(fā)布時間:2018-11-30 17:48:25 閱讀量:1128

數(shù)據(jù)庫作為Android數(shù)據(jù)存儲重要的一部分,相信很多應用中都會用到,面試也會遇到很多關于數(shù)據(jù)庫的問題。實際開發(fā)中我沒遇到過特別復雜的數(shù)據(jù)庫使用,所以對這一塊的優(yōu)化沒怎么研究過。 

以前面試的時候被問到過這么一個問題: 

面試官:數(shù)據(jù)庫并發(fā)訪問怎么處理? 

我:給增刪改查方法加鎖。 

面試官:那樣會有什么問題? 

我:效率低。 

面試官:怎么解決? 

我:不太清楚啊。。。


我一直認為Android開發(fā)不會涉及到數(shù)據(jù)庫大量線程訪問數(shù)據(jù)庫的問題,所以方法加鎖的效率問題是可以容忍的,搜索這個問題的解決方式,發(fā)現(xiàn)大家也都是粗暴的用synchronize來解決。 

我覺得即使優(yōu)化也是在加鎖的方式上優(yōu)化,關于加鎖的高級用法我沒有研究過,所以一直沒有太在意過這個問題(不要罵我不思進取不去學習高級用法。。。)。


后來不知道在哪看了什么東東受到了啟發(fā),我們可以用隊列來解決這個問題?。?!


一個思路就是:創(chuàng)建一個單線程的線程池,所有的數(shù)據(jù)庫操作都用這個線程池來操作


下面是我的demo,非常簡單:


public class DBHelper extends SQLiteOpenHelper{


    private static String DBName = "TestDB";

    private static int DBVersion = 1;

    private SQLiteDatabase db;

    private static DBHelper INSTANCE;

    // 不用的時候需要關閉線程池

    private ExecutorService pool;


    private DBHelper(Context context) {

        super(context, DBName, null, DBVersion);

        db = getReadableDatabase();

        // 創(chuàng)建一個單線程池

        pool = Executors.newSingleThreadExecutor();

    }


    // 單例

    public static DBHelper getInstance(Context context){

        if(INSTANCE == null){

            synchronized (DBHelper.class){

                if (INSTANCE == null){

                    INSTANCE = new DBHelper(context.getApplicationContext());

                }

            }

        }

        return INSTANCE;

    }


    @Override

    public void onCreate(SQLiteDatabase db) {


    }


    @Override

    public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {


    }


    // 模擬一個插入,參數(shù)隨便寫了,返回值和SQLiteDatabase的插入方法一樣都是long類型,表示插入的id

    public long insert(final String param){

        Future<Long> submit = pool.submit(new Callable<Long>() {

            @Override

            public Long call() throws Exception {

                // 休眠1秒,模擬耗時

                Thread.sleep(1000);

                Log.e("lzw","插入 param: " + param);

                return 100L;

            }

        });

        long id = -1;

        try {

            // 拿操作結果,這里會阻塞

            id = submit.get();

        } catch (InterruptedException e) {

            e.printStackTrace();

        } catch (ExecutionException e) {

            e.printStackTrace();

        }

        return  id;

    }

}

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

54

55

56

57

58

59

60

61

整個DBHelper是一個單例,在構造里實例化了一個單線程池,insert方法是表示插入,參數(shù)隨便寫了一個,我們通過pool.submit方法把任務提交到了線程池進行執(zhí)行,返回了一個Future類型的變量, 

后面調用Future的get方法可以拿到返回值,get方法會阻塞,直到執(zhí)行完call方法里的內容并拿到返回值。關于ExecutorService和Future的使用不是本文重點,大家自行學習。


下面是測試Activity:


public class MainActivity extends AppCompatActivity {


    private TextView tv;

    private DBHelper helper;

    private int param = 0;

    static Handler handler = new Handler();


    @Override

    protected void onCreate(Bundle savedInstanceState) {

        super.onCreate(savedInstanceState);

        setContentView(R.layout.activity_main);

        tv = (TextView) findViewById(R.id.content);

        helper = DBHelper.getInstance(this);

        findViewById(R.id.insert).setOnClickListener(new View.OnClickListener() {

            @Override

            public void onClick(View v) {

                new Thread(new Runnable() {

                    @Override

                    public void run() {

                        param++;

                        final int param2 = param;

                        final long id = helper.insert("----> " + param2);

                        handler.post(new Runnable() {

                            @Override

                            public void run() {

                                tv.append(id + ":" + param2 + "\n");

                            }

                        });

                    }

                }).start();

            }

        });

    }

}

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

所有的操作都會逐條執(zhí)行。 

效果圖如下: 



以上就是所有的代碼,只是講了一下思路,用的時候大家根據(jù)自己的情況去封裝就好了。


其實擴展一下,大家可以自己寫一個生產(chǎn)者消費者模型也可以解決這個問題,核心思路和上面的方法都一樣,就是一個阻塞隊列,需要修改數(shù)據(jù)庫的,把需求添加進隊列,DBHelper從隊列中不斷取并操作數(shù)據(jù)庫。


其實Handler的思路也是這么個套路。


不多說了,下面是代碼地址: 

https://github.com/dreamlizhengwei/DatabaseDemo

--------------------- 



分享:
評論:
你還沒有登錄,請先