2017-02-15 18 views
0

onStartMethodで同期マップを使用し、キーがまだ格納されていないことを確認することで、サービス上で重複したタスクを実行しないようにしようとしています。しかし、これまでのところ動作していません。すぐにサービスを2回起動すると同じことが2回実行されます。onStartCommandサービス内の同期マップ

public void onCreate() { 
      SYNCED_TABLES = Collections.synchronizedMap(new Hashtable<>()); 
} 
public int onStartCommand(Intent intent, int flags, int startId) { 
      synchronized (SYNCED_TABLES){ 
       if(!SYNCED_TABLES.containsKey(intent.getStringExtra(KEY))){ 
        SYNCED_TABLES.put(intent.getStringExtra(KEY), true); 
        /* Do stuff on a Handler thread */ 
       } 
       else{ 
        Log.d(TAG, "Tried to execute the same task twice " + intent.getStringExtra(KEY)); 
       } 
      } 

} 
+0

なぜIntentServiceを使用しないのですか? – Submersed

+0

スレッドハンドラで行われた作業は、サーバへのポストリクエストです。要求をマルチスレッドにしたい(いくつかの異なるデータベースがある) – Julio

答えて

0

SYNCED_TABLESの初期化はスレッドセーフではありません。結果として、このフィールドに複数のオブジェクトが割り当てられている可能性があります。つまり、複数のオブジェクトがロックされている可能性があります。

finalフィールドとしてSYNCED_TABLESを宣言し、右がそれを初期化します。

public class Foo { 
    final SYNCED_TABLES = Collections.synchronizedMap(new Hashtable<>()); 
} 

これは、あなたのオブジェクトの寿命にわたって単一のロックを持っていることを保証します。

+0

それは動作するが、サービスが停止した後、マップは再びインスタンス化されるか?私はちょうど数分後に再びサービスを実行しようとしたため、古い値がまだ格納されていたために実行されませんでした。 – Julio

+0

コレクションを空にするにはhttps://docs.oracle.com/javase/7/docs/api/java/util/Collection.html#clear()があります。それがあなたのニーズに合っているなら、あなたは 'onCreate()'でそれを呼び出すことができます。 – aha

+0

ありがとう、それは今働きます – Julio

関連する問題