java中同步ArrayList的正确方法

java中同步ArrayList的正确方法,java,arraylist,concurrency,synchronization,Java,Arraylist,Concurrency,Synchronization,我不确定这是否是同步我的ArrayList的正确方法 我在队列中有一个ArrayList,它是从registerInQueue函数传入的 ArrayList<Record> in_queue = null; public void registerInQueue(ArrayList in_queue) { this.in_queue = in_queue; } 这是正确的,并记录在案: 但是,要清除列表,只需调用。是的,这是正确的方法,但是如果希望所有删除都是安全的,则

我不确定这是否是同步我的
ArrayList
的正确方法

我在队列中有一个
ArrayList
,它是从
registerInQueue
函数传入的

ArrayList<Record> in_queue = null;

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

这是正确的,并记录在案:


但是,要清除列表,只需调用。

是的,这是正确的方法,但是如果希望所有删除都是安全的,则需要同步块-除非队列为空,否则不允许删除。我的猜测是,您只需要安全的队列和出列操作,这样就可以删除同步块


但是,Java中有一些非常高级的并发队列,例如,您要同步两次,这是毫无意义的,并且可能会减慢代码的速度:在列表中迭代时的更改需要对整个操作进行同步,您正在使用
synchronized(在队列列表中)执行此操作
在这种情况下,使用
Collections.synchronizedList()
是多余的(它创建了一个用于同步单个操作的包装器)

但是,由于您要完全清空列表,因此迭代删除第一个元素是最糟糕的方法,对于每个元素,必须复制以下所有元素,这使得这是一个O(n^2)操作-对于较大的列表,速度非常慢

相反,只需调用
clear()
——无需迭代

编辑: 如果以后需要对
Collections.synchronizedList()
进行单方法同步,则这是正确的方法:

List<Record> in_queue_list = Collections.synchronizedList(in_queue);
in_queue_list.clear(); // synchronized implicitly, 
List in_queue_List=Collections.synchronizedList(in_queue);
在队列列表中。清除();//隐式同步,

但在许多情况下,单一方法同步是不够的(例如,对于所有迭代,或者当您得到一个值时,基于它进行计算,并用结果替换它)。在这种情况下,您必须使用手动同步,因此,
Collections.synchronizedList()
只是无用的额外开销。

看看您的示例,我认为(或其同级)可能有用。它们为您负责同步,因此线程可以写入队列或查看/获取,而无需您进行额外的同步工作。

让我们获取一个普通列表(由ArrayList类实现)并使其同步。这在SynchronizedListExample类中显示。 我们向Collections.synchronizedList方法传递一个新的字符串数组列表。该方法返回一个同步的字符串列表。 //这是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());
            }
        }    
    }
}
package com.mnas.technology.automation.utility;
导入java.util.ArrayList;
导入java.util.Collections;
导入java.util.Iterator;
导入java.util.List;
导入org.apache.log4j.Logger;
/**
* 
*@作者manoj.kumar
*@email kumaranoj。mtech@gmail.com
* 
*/
公共类SynchronizedArrayList{
静态记录器log=Logger.getLogger(SynchronizedArrayList.class.getName());
公共静态void main(字符串[]args){
List synchronizedList=Collections.synchronizedList(新的ArrayList());
synchronizedList.add(“Aditya”);
synchronizedList.add(“Siddharth”);
synchronizedList.add(“Manoj”);
//在对同步列表进行迭代时,我们需要同步对同步列表的访问
已同步(synchronizedList){
迭代器迭代器=synchronizedList.Iterator();
while(iterator.hasNext()){
info(“同步数组列表项:“+iterator.next());
}
}    
}
}
请注意,在遍历列表时,仍然使用锁定synchronizedList对象的同步块来完成此访问。
通常,对同步集合的迭代应该在同步块中完成

在这里同步两次并不是毫无意义的:它确保循环运行时,没有其他人可以修改列表。不过,不使用
clear()
有点过头了。:)所以我应该做一些类似的事情:synchronized((列表)in_queue)?好的!实际上,我删除了一些代码来简化它。我不会对clear()/remove()有任何问题。谢谢=]@Bombe:不,这完全没有意义。正如我所写的,使用Collections.synchronizedList()是多余的,这不会带来任何效果。确切的错误消息是什么?发生在哪一行?错误消息“field not static final”无法通过Google找到,因此我怀疑这是您实际得到的。您无法真正升级要同步的列表,因为您正在被传递一个引用,因此您并不真正拥有它。无论给你什么样的引用,都可以同时修改它传递给你的原始列表。无论添加什么同步,除非明确知道列表将由其固有锁保护。我将在队列上的任何操作周围放置一个同步块。谢谢谢谢你的建议!这就是我正在尝试做的,但不确定是否要限制数组的大小。我会记住这一点注意,还有一个LinkedBlockingQueue。而且你不一定需要施加限制。
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());
            }
        }    
    }
}