0
public class Rule{
 private Integer ruleId;
 private String name;
 private Date startdate;
 private Date endDate;

 // getters & setters
}
public class ClassA{
  public static List<Rule> ruleList = new ArrayList<Rule>();
  public void populateRule(){
   //Retrieve all rules; Here the rules are being added or deleted by the administration.
   //So it is required to retrieve the rules every time the Job runs.
    ruleList.clear();
    ruleList.addAll(RuleService.retrieveRules());
  }
}

public class UserClassA1{
  ClassA oClassA=Factory.getInstance(ClassA.class);
  List<Rule> rules=oClassA.populateRule();
  for(Rule oRule:rules){
  // do some stuff.
  } 
}
public class UserClassA2{
 ClassA oClassA=Factory.getInstance(ClassA.class);
List<Rule> rules=oClassA.populateRule();
for(Rule oRule:rules){
  // do some stuff.
  } 
}

ここで、UserClassA1とUserClassA2は異なるアクティビティを実行していますが、どちらも同じ静的リストを使用しており、開始時にリストをリセットして新しいリストにデータを入力します。

私の問題は、UserClassA1がリストに入力した後に動作を開始すると、UserClassA2が実行を開始してリストをクリアしてから、リストに入力することです。リストをクリアしてから入力するまでのこの時間のギャップでは、UserClassA1はリストのように正しく機能していません。クリアされました。

ruleListリストをロックして、インスタンスのいずれかがリストにデータを入力している間、他のインスタンスがリストを使用しないようにします。

ヘルプpls..

4

5 に答える 5

1

classAで、ruleListをCopyOnWriteArrayList(java.util.concurrent内)として宣言します。リストが変更されるたびに、新しいコピーが作成されます。リスト上の既存のイテレータは、書き込み操作の影響を受けません。

このようにすると、ruleListのインスタンスは1つになりますが、スレッドセーフになります。

Javadoc:http ://docs.oracle.com/javase/7/docs/api/java/util/concurrent/CopyOnWriteArrayList.html

于 2012-08-17T15:34:49.497 に答える
0

ClassAメソッドの各呼び出し元に新しいリストを配布するように変更することを検討する必要がありますpopulateRule。そうすれば、呼び出し元は、その後の。の呼び出しを気にすることなく、返されたリストを適切と思われる方法で使用できますpopulateRule。例:

public class ClassA {
  public List<Rule> populateRule() {
    // Retrieve all rules; Here the rules are being added or deleted by 
    // the administration. So it is required to retrieve the rules every 
    // time the Job runs.
    return new ArrayList(RuleService.retrieveRules());
  }
}
于 2012-08-06T23:07:37.563 に答える
0

単純な(力ずくではありますが)方法は、Collections.synchronizedList();を使用することです。

public static List<Rule> ruleList = Collections.synchronizedList(new ArrayList<Rule>());
于 2012-08-06T07:30:47.450 に答える
0

一貫した状態 (完全に入力された状態) でリストを表示する必要があると思います。ruleListプライベートにすることから始めることができます。また、2 つのスレッドが同時にデータを入力できないようにするには、populateRule同期を行います。

しかし、 へのClassAアクセスを必要とする他のメソッドがない限りruleList、クラスの防御的でスレッドセーフで単純なバージョンは次のようになります。

public class ClassA{
    public void populateRule() {
        //Retrieve all rules; Here the rules are being added or deleted by the administration.
        //So it is required to retrieve the rules every time the Job runs.
        return Collections.unmodifiableList(RuleService.retrieveRules());
    }
}
于 2012-08-06T07:00:10.730 に答える
0

標準的な答えは、リストにアクセスするコードを でラップすることですsynchronized(ClassA.ruleList) { ... }。ただし、プリミティブなどをいじるとsynchronizedエラーが発生しやすくなるためjava.util.concurrent、 などの の上位レベルの構造を常に使用するようにしてLockください。

ただし、この場合、コードを少しリファクタリングすることを検討することをお勧めします。ruleList例えばfactorメソッドでローカル変数を作ってみてはどうでしょうか。

于 2012-08-06T06:55:29.447 に答える