質問

これが ArrayList を同期する正しい方法かどうかわかりません。

registerInQueue 関数から渡される ArrayList in_queue があります。

ArrayList<Record> in_queue = null;

public void registerInQueue(ArrayList in_queue)
{
    this.in_queue = in_queue;
}

今、同期しようとしています。これは私の in_queue オブジェクトを正しく同期していますか?

List<Record> in_queue_list = Collections.synchronizedList(in_queue);

synchronized (in_queue_list) {
    while (in_queue_list.size() > 0) {
        in_queue_list.remove(0);
    }
}
役に立ちましたか?

解決

2回同期しますが、これは無意味であり、コードの速度を低下させる可能性があります。リストの繰り返し処理中の変更には、 synchronized(in_queue_list)で行っている操作全体の同期が必要ですその場合、 Collections.synchronizedList()は不要です(個々の操作を同期するラッパーを作成します)。

ただし、リストを完全に空にしているため、最初の要素を繰り返し削除するのが最も悪い方法です。各要素のサイズは後続のすべての要素をコピーする必要があり、これをO(n ^ 2)にします操作-大きいリストでは恐ろしく遅い。

代わりに、単に clear()を呼び出します-繰り返しは不要です。

編集: 後で Collections.synchronizedList()の単一メソッドの同期が必要な場合、これが正しい方法です:

List<Record> in_queue_list = Collections.synchronizedList(in_queue);
in_queue_list.clear(); // synchronized implicitly, 

しかし、多くの場合、単一メソッドの同期は不十分です(たとえば、すべての反復、または値を取得し、それに基づいて計算を行い、結果で置き換えます)。その場合、とにかく手動同期を使用する必要があるため、 Collections.synchronizedList()は無駄な追加オーバーヘッドにすぎません。

他のヒント

例を見ると、 ArrayBlockingQueue (またはその兄弟)が役に立つかもしれません。彼らはあなたのために同期の世話をするので、スレッドはあなたの側で追加の同期作業なしでキューに書き込むか、ピーク/テイクすることができます。

それは正しく、文書化されています:

http ://java.sun.com/javase/6/docs/api/java/util/Collections.html#synchronizedList(java.util.List)

ただし、リストをクリアするには、 List.clear()

はい、それは正しい方法ですが、すべての削除を安全にしたい場合は同期ブロックが必要です-キューが空でない限り、削除は許可されません。私の推測では、安全なキュー操作とデキュー操作だけが必要なので、同期ブロックを削除できます。

ただし、 ConcurrentLinkedQueue

通常のリスト(ArrayListクラスで実装)を取得して、同期させます。これはSynchronizedListExampleクラスに示されています。     Collections.synchronizedListメソッドに新しい文字列のArrayListを渡します。このメソッドは、文字列の同期リストを返します。     // SynchronizedArrayListクラス

package com.mnas.technology.automation.utility;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Iterator;
import java.util.List;
import org.apache.log4j.Logger;
/**
* 
* @author manoj.kumar
* @email kumarmanoj.mtech@gmail.com
* 
*/
public class SynchronizedArrayList {
    static Logger log = Logger.getLogger(SynchronizedArrayList.class.getName());
    public static void main(String[] args) {    
        List<String> synchronizedList = Collections.synchronizedList(new ArrayList<String>());
        synchronizedList.add("Aditya");
        synchronizedList.add("Siddharth");
        synchronizedList.add("Manoj");
        // when iterating over a synchronized list, we need to synchronize access to the synchronized list
        synchronized (synchronizedList) {
            Iterator<String> iterator = synchronizedList.iterator();
            while (iterator.hasNext()) {
                log.info("Synchronized Array List Items: " + iterator.next());
            }
        }    
    }
}

リストを繰り返し処理する場合、このアクセスはまだsynchronizedListオブジェクトをロックする同期ブロックを使用して行われます。 一般に、同期されたコレクションの繰り返しは、同期されたブロックで実行する必要があります

ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top