在java中同步ArrayList的正确方法
我不确定这是否是同步我的ArrayList
的正确方法。在java中同步ArrayList的正确方法
我有一个ArrayList
in_queue
这是从registerInQueue
功能传入。
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);
}
}
你同步两次,这是毫无意义的,可能会减慢代码:变化,同时遍历列表需要在整个操作的synchronnization ,你在做什么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()
只是无用的额外开销。
是的,这是正确的方法,但如果您希望所有删除一起保证安全,则需要同步的块 - 除非队列为空,否则不允许删除。我的猜测是,你只是想要安全的队列和出队操作,所以你可以删除同步块。
然而,在Java中远远先进的并发队列如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 [email protected]
*
*/
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());
}
}
}
}
注意,遍历列表时,该访问依然采用了synchronized块的synchronizedList对象锁定完成。 通常,迭代同步的集合应在同步块中完成
由于您正在传递引用,因此您无法真正升级列表以进行同步,因此您并不真正拥有它。无论给你什么参考,仍然可以修改它同时通过你的原始列表。无论您添加什么同步,除非明确知道该列表将被内部锁定保护。 – 2009-09-16 08:46:58
我将在队列上的任何操作周围放置一个同步块。谢谢! – bob 2009-09-16 09:09:56