Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/sql-server-2005/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 与ArrayList相比,向量填充所需的时间更少_Java_Arraylist_Vector_Collections - Fatal编程技术网

Java 与ArrayList相比,向量填充所需的时间更少

Java 与ArrayList相比,向量填充所需的时间更少,java,arraylist,vector,collections,Java,Arraylist,Vector,Collections,我正在浏览以下文章: 文章说, 您知道,Vector和Hashtable是Java历史早期存在的两个集合,它们从一开始就是为线程安全而设计的(如果您有机会查看它们的源代码,您将看到它们的方法都是同步的!)。但是,它们很快就会暴露出多线程程序中的低性能。您可能知道,同步需要锁,而锁总是需要时间来监视,这会降低性能 [我还使用卡尺进行了基准测试;请听我讲完这一点] 还提供了一个示例代码: public class CollectionsThreadSafeTest { public vo

我正在浏览以下文章:

文章说,

您知道,Vector和Hashtable是Java历史早期存在的两个集合,它们从一开始就是为线程安全而设计的(如果您有机会查看它们的源代码,您将看到它们的方法都是同步的!)。但是,它们很快就会暴露出多线程程序中的低性能。您可能知道,同步需要锁,而锁总是需要时间来监视,这会降低性能

[我还使用卡尺进行了基准测试;请听我讲完这一点]

还提供了一个示例代码:

public class CollectionsThreadSafeTest {

    public void testVector() {
        long startTime = System.currentTimeMillis();

        Vector<Integer> vector = new Vector<>();
        for (int i = 0; i < 10_000_000; i++) {
            vector.addElement(i);
        }

        long endTime = System.currentTimeMillis();
        long totalTime = endTime - startTime;
        System.out.println("Test Vector: " + totalTime + " ms");
    }

    public void testArrayList() {
        long startTime = System.currentTimeMillis();

        List<Integer> list = new ArrayList<>();
        for (int i = 0; i < 10_000_000; i++) {
            list.add(i);
        }

        long endTime = System.currentTimeMillis();
        long totalTime = endTime - startTime;
        System.out.println("Test ArrayList: " + totalTime + " ms");
    }

    public static void main(String[] args) {
        CollectionsThreadSafeTest tester = new CollectionsThreadSafeTest();

        tester.testVector();
        tester.testArrayList();
    }
}
但当我在我的机器上运行它时,它给了我以下结果:

Test Vector: 521 ms
Test ArrayList: 2273 ms
我觉得这很奇怪。我认为做一个微型基准测试会更好。因此,我使用卡尺为上述内容编写了一个基准测试。代码如下:

Test Vector: 9266 ms
Test ArrayList: 4588 ms
public class CollectionsThreadSafeTest extends SimpleBenchmark {

    public static final int ELEMENTS = 10_000_000;

    public void timeVector(int reps) {
        for (int i = 0; i < reps; i++) {
            Vector<Integer> vector = new Vector<>();
            for (int k = 0; k < ELEMENTS; k++) {
                vector.addElement(k);
            }
        }
    }

    public void timeArrayList(int reps) {
        for (int i = 0; i < reps; i++) {
            List<Integer> list = new ArrayList<>();
            for (int k = 0; k < ELEMENTS; k++) {
                list.add(k);
            }
        }
    }

    public static void main(String[] args) {
        String[] classesToTest = { CollectionsThreadSafeTest.class.getName() };
        Runner.main(classesToTest);
    }
}
我有点困惑。这里发生了什么?我是不是做错了什么(那真的很尴尬)

如果这是预期的行为,那么背后的解释是什么


更新#1

在读取了之后,我通过更改
向量
阵列列表
的初始容量值来运行卡尺测试。以下是计时(毫秒):


感谢所有的输入:)

在多线程环境中,向量的速度应该会较慢。在您的情况下,它应该是轻量级的。最好通过从10000个不同线程添加这些项来进行测试,ArrayList和Vector都有相同的添加方法:

ensureCapacity();
    elementData[elementCount++] = newElement;
区别只有一个。Vector的add方法已同步,ArrayList的则未同步。从理论上讲,同步方法比不同步方法慢


要提高add方法的性能,必须在构造函数中指定
initialCapacity
,或调用方法
ensureCapacity
。这将创建您需要的内部数组,因此无需重新创建它。

您并不是在这里真正测试
add()
方法。您正在测试
向量
数组列表
的不同增长方式。
Vector
满时大小会翻倍,但是
ArrayList
有一些更精确的逻辑,可以防止内部数组以指数形式增长并浪费内存


如果两个类的初始容量都大于10000000,则它们不需要调整大小,您只需分析添加的部分。

Ok。但是他们为本文中的示例代码提供的输出呢?他们只是在不使用线程的情况下对添加操作进行计时。这并不能解释为什么在单线程环境中添加操作会更快。这如何回答这个问题?小提示:除非在某些使用模式下,使用同步方法并不能使类线程安全。例如,给定一个
向量foos
,在列表中出现一个
foo1
,序列
foos.remove(foo1);foos.add(foo1)
由两个线程同时运行或多或少会导致列表中出现两次
foo1
,或仅出现一次。无论基准测试的结果如何,尽管存在缺陷,但您不应该使用这些遗留类,
哈希表
向量
。这不是速度或线程“安全”的问题,而是使用不过时的替代品的问题,这些替代品缺少遗留类型的多余粗糙。已经十九年了;有足够的时间来适应更换。@LewBloch使用的卡尺也不好,或者他们的方法总体上不好?因此,如果我指定了尺寸,我将能够得到实际时间?取决于您所说的“实际”是什么意思。您将从等式中删除大小调整。在
向量上调整大小的速度更快,因为一段时间后,内部容量变得巨大,不再需要调整大小,而
数组列表
以更平静的方式增长,节省内存,但如果事先没有计划,则需要更多的调整大小。我将初始容量设置为10_000_000,然后再次运行卡尺测试。获得
ArrayList:67.1ms
Vector:49.2ms
。所以,有点像我得到的。我不熟悉卡钳。JMH似乎是我在这里看到的基准测试中最受欢迎的。在基准测试中这样猜测不是一个好主意。首先,您需要使用JMH复制结果,以确保这不是基准测试中的错误,然后如果您仍然感兴趣,您可以进一步研究它。
Initial Capacity    Vector  ArrayList
-------------------------------------
10_000_000          49.2    67.1
10_000_001          48.9    71.2
10_000_010          48.1    61.2
10_000_100          43.9    70.1
10_001_000          45.6    70.6
10_010_000          44.8    68.0
10_100_000          52.8    64.6
11_000_000          52.7    71.7
20_000_000          74.0    51.8
-------------------------------------
ensureCapacity();
    elementData[elementCount++] = newElement;