2

シングルトンパターンを実装するクラスがあり、、、、およびの3つのSQLiteOpenHelperメソッドがあります。7つのスレッド(特定のスケジュールでトリガーされる)がデータベースにアクセスします。そのうちの6つはを使用するだけで、もう1つはデータベースが終了する前に使用して呼び出します。addLogs()getLogs()deleteLogs()BroadcastReceiveraddLogs()getLogs()deleteLogs()

私の問題は、最後のスレッドがSQLiteデータベースに対して2つの異なる呼び出しを行うため、他のスレッドが呼び出されるaddLogs()前でも呼び出すことができdeleteLogs()、出力が破損することです。SQLiteOpenHelper1つのスレッドで、への2つの呼び出しを単一のアトミックトランザクションとして処理するにはどうすればよいですか?

私が試したこと:で静的ReentrantLockメンバーを作成し、トランザクションの前後に7つのスレッドのすべてから呼び出しSQLiteOpenHelperます。他の6つのスレッドは、最後のスレッドがまだロックを持っていても通過します。ロックは前に呼び出し、後に解放します。lock()unlock()getLogs()deleteLogs()

更新:これは、2つのメソッドにアクセスする7番目のスレッドです。

public class Uploader extends Thread {

    private Context context;

    public Uploader(Context context) {
        this.context = context;
    }

    @Override
    public void run() {
        Logger.d("STARTED: Uploader");
        DB db = DB.getInstance(context);
        List<JsonLog> logs = db.getLogs(); // FIRST CALL
        String json = new Gson().toJson(logs); // convert to JSON

        // connect to the server and upload
        HttpClient client = new DefaultHttpClient();
        HttpPost post = new HttpPost(This.URL);
        post.setHeader("content-type", "application/json");
        try {
            Logger.d("to upload: " + json);
            StringEntity se = new StringEntity(json);
            post.setEntity(se);
            StatusLine status = client.execute(post).getStatusLine();
            // if upload is successful
            if (status.getStatusCode() == HttpStatus.SC_OK) {
                db.deleteLogs(); // SECOND CALL
            } else {
                Logger.d("Uploader failed. " + status.getStatusCode() + ": " + status.getReasonPhrase());
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        Logger.d("FINISHED: Uploader");
    }

}
4

1 に答える 1

3

SQLite には のようなトランザクションがあり、Tx をコミットするようにマークしdb.beginTransaction()、最後に Tx を完了済みとしてマークします。db.setTransactionSuccessful()db.endTransaction()

したがって、あなたgetLogs()はそれを完了した(そして成功した)beginTransactiondeleteLogsマークすることができます。

[更新]コードスニペットを使用すると、おそらくbeginTransaction最初の呼び出しの前にブロック内で呼び出しfinallytry-catchブロック呼び出しにendTransaction. 部分の最後でtry、ステータスが OK の場合は、コールしますsetTransactionSuccessful(コールの後) delete

于 2012-12-24T13:35:35.507 に答える