在java中同步ArrayList的正确方法

时间:2022-03-11 07:10:13

I'm not sure if this is the correct way to synchronize my ArrayList.

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

I have an ArrayList in_queue which is passed in from the registerInQueue function.

我有一个ArrayList in_queue,它从registerInQueue函数传入。

ArrayList<Record> in_queue = null;

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

Now I'm trying to synchronize it. Is this sychronizing my in_queue object correctly?

现在我正在尝试同步它。这是我的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);
    }
}

5 个解决方案

#1


43  

You're synchronizing twice, which is pointless and possibly slows down the code: changes while iterating over the list need a synchronnization over the entire operation, which you are doing with synchronized (in_queue_list) Using Collections.synchronizedList() is superfluous in that case (it creates a wrapper that synchronizes individual operations).

你正在进行两次同步,这是毫无意义的,可能会减慢代码:迭代列表时的更改需要在整个操作上进行同步,你正在使用synchronized进行同步(in_queue_list)在这种情况下使用Collections.synchronizedList()是多余的(它创建一个同步单个操作的包装器)。

However, since you are emptying the list completely, the iterated removal of the first element is the worst possible way to do it, sice for each element all following elements have to be copied, making this an O(n^2) operation - horribly slow for larger lists.

但是,由于您正在完全清空列表,因此迭代删除第一个元素是最糟糕的方法,每个元素的sice必须复制所有后续元素,这使得它成为O(n ^ 2)操作 - 可怕较大的列表速度慢。

Instead, simply call clear() - no iteration needed.

相反,只需调用clear() - 不需要迭代。

Edit: If you need the single-method synchronization of Collections.synchronizedList() later on, then this is the correct way:

编辑:如果稍后需要Collections.synchronizedList()的单方法同步,那么这是正确的方法:

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

But in many cases, the single-method synchronization is insufficient (e.g. for all iteration, or when you get a value, do computations based on it, and replace it with the result). In that case, you have to use manual synchronization anyway, so Collections.synchronizedList() is just useless additional overhead.

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

#2


8  

Looking at your example, I think ArrayBlockingQueue (or its siblings) may be of use. They look after the synchronisation for you, so threads can write to the queue or peek/take without additional synchronisation work on your part.

看看你的例子,我认为ArrayBlockingQueue(或它的兄弟姐妹)可能有用。他们会为您管理同步,因此线程可以写入队列或查看/获取,而无需您进行额外的同步工作。

#3


5  

That's correct, and documented:

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

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

However, to clear the list, just call List.clear().

但是,要清除列表,只需调用List.clear()。

#4


5  

Yes it is the correct way, but the synchronised block is required if you want all the removals together to be safe - unless the queue is empty no removals allowed. My guess is that you just want safe queue and dequeue operations, so you can remove the synchronised block.

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

However, there are far advanced concurrent queues in Java such as ConcurrentLinkedQueue

但是,Java中有很多高级并发队列,例如ConcurrentLinkedQueue

#5


1  

Let's take a normal list (implemented by the ArrayList class) and make it synchronized. This is shown in the SynchronizedListExample class. We pass the Collections.synchronizedList method a new ArrayList of Strings. The method returns a synchronized List of Strings. //Here is SynchronizedArrayList class

让我们采用一个正常的列表(由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());
            }
        }    
    }
}

Notice that when iterating over the list, this access is still done using a synchronized block that locks on the synchronizedList object. In general, iterating over a synchronized collection should be done in a synchronized block

请注意,在遍历列表时,仍然使用锁定synchronizedList对象的synchronized块完成此访问。通常,迭代同步集合应该在同步块中完成

#1


43  

You're synchronizing twice, which is pointless and possibly slows down the code: changes while iterating over the list need a synchronnization over the entire operation, which you are doing with synchronized (in_queue_list) Using Collections.synchronizedList() is superfluous in that case (it creates a wrapper that synchronizes individual operations).

你正在进行两次同步,这是毫无意义的,可能会减慢代码:迭代列表时的更改需要在整个操作上进行同步,你正在使用synchronized进行同步(in_queue_list)在这种情况下使用Collections.synchronizedList()是多余的(它创建一个同步单个操作的包装器)。

However, since you are emptying the list completely, the iterated removal of the first element is the worst possible way to do it, sice for each element all following elements have to be copied, making this an O(n^2) operation - horribly slow for larger lists.

但是,由于您正在完全清空列表,因此迭代删除第一个元素是最糟糕的方法,每个元素的sice必须复制所有后续元素,这使得它成为O(n ^ 2)操作 - 可怕较大的列表速度慢。

Instead, simply call clear() - no iteration needed.

相反,只需调用clear() - 不需要迭代。

Edit: If you need the single-method synchronization of Collections.synchronizedList() later on, then this is the correct way:

编辑:如果稍后需要Collections.synchronizedList()的单方法同步,那么这是正确的方法:

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

But in many cases, the single-method synchronization is insufficient (e.g. for all iteration, or when you get a value, do computations based on it, and replace it with the result). In that case, you have to use manual synchronization anyway, so Collections.synchronizedList() is just useless additional overhead.

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

#2


8  

Looking at your example, I think ArrayBlockingQueue (or its siblings) may be of use. They look after the synchronisation for you, so threads can write to the queue or peek/take without additional synchronisation work on your part.

看看你的例子,我认为ArrayBlockingQueue(或它的兄弟姐妹)可能有用。他们会为您管理同步,因此线程可以写入队列或查看/获取,而无需您进行额外的同步工作。

#3


5  

That's correct, and documented:

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

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

However, to clear the list, just call List.clear().

但是,要清除列表,只需调用List.clear()。

#4


5  

Yes it is the correct way, but the synchronised block is required if you want all the removals together to be safe - unless the queue is empty no removals allowed. My guess is that you just want safe queue and dequeue operations, so you can remove the synchronised block.

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

However, there are far advanced concurrent queues in Java such as ConcurrentLinkedQueue

但是,Java中有很多高级并发队列,例如ConcurrentLinkedQueue

#5


1  

Let's take a normal list (implemented by the ArrayList class) and make it synchronized. This is shown in the SynchronizedListExample class. We pass the Collections.synchronizedList method a new ArrayList of Strings. The method returns a synchronized List of Strings. //Here is SynchronizedArrayList class

让我们采用一个正常的列表(由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());
            }
        }    
    }
}

Notice that when iterating over the list, this access is still done using a synchronized block that locks on the synchronizedList object. In general, iterating over a synchronized collection should be done in a synchronized block

请注意,在遍历列表时,仍然使用锁定synchronizedList对象的synchronized块完成此访问。通常,迭代同步集合应该在同步块中完成