当前位置: 首页 > 面试题库 >

Java ArrayList类中的数据争夺

楚皓君
2023-03-14
问题内容

我正在阅读,CopyOnWriteArrayList并且想知道如何在ArrayList课堂上演示数据竞赛。基本上,我正在尝试模拟一种ArrayList失败的情况,因此有必要使用CopyOnWriteArrayList。关于如何模拟这一点的任何建议。


问题答案:

竞争是指两个(或多个)线程尝试对共享数据进行操作,而最终输出取决于访问数据的顺序(并且该顺序是不确定的)

从维基百科:

竞赛状况或竞赛危害是电子系统或过程中的缺陷,由此过程的输出和/或结果意外地且严重地取决于其他事件的顺序或时间。该术语起源于两个信号相互竞争以首先影响输出的想法。

例如:

public class Test  {
    private static List<String> list = new CopyOnWriteArrayList<String>();

    public static void main(String[] args) throws Exception {
        ExecutorService e = Executors.newFixedThreadPool(5);
        e.execute(new WriterTask());
        e.execute(new WriterTask());
        e.execute(new WriterTask());
        e.execute(new WriterTask());
        e.execute(new WriterTask());

        e.awaitTermination(20, TimeUnit.SECONDS);
    }

    static class WriterTask implements Runnable {

        @Override
        public void run() {
            for (int i = 0; i < 25000; i ++) {
                list.add("a");
            }
        }
    }
}

但是,当ArrayList与一起使用时,此操作将失败ArrayIndexOutOfbounds。这是因为在插入之ensureCapacity(..)前应先调用,以确保内部数组可以保存新数据。这是发生了什么:

  • 第一个线程调用add(..),然后依次调用ensureCapacity(currentSize + 1)
  • 在第一个线程实际增加大小之前,第二个线程也调用ensureCapacity(currentSize + 1)
  • 因为两个都读取了的初始值currentSize,所以内部数组的新大小为currentSize + 1
  • 这两个线程使将旧数组复制到扩展数组中并具有新大小(这 不能容纳两个加法项 )的操作很昂贵。
  • 然后他们每个都尝试将新元素分配给array[size++]。第一个成功,第二个失败,因为由于rece条件,内部数组未正确扩展。

发生这种情况是因为两个线程试图在同一结构上同时添加项目,而其中一个的添加却覆盖了另一个的添加(即第一个丢失)

的另一个好处 CopyOnWriteArrayList

  • 多个线程写入 ArrayList
  • 一个线程迭代ArrayList。肯定会得到ConcurrentModificationException

演示方法如下:

public class Test  {
    private static List<String> list = new ArrayList<String>();

    public static void main(String[] args) throws Exception {
        ExecutorService e = Executors.newFixedThreadPool(2);
        e.execute(new WriterTask());
        e.execute(new ReaderTask());
    }

    static class ReaderTask implements Runnable {
        @Override
        public void run() {
            while (true) {
                for (String s : list) {
                    System.out.println(s);
                }
            }
        }
    }

    static class WriterTask implements Runnable {
        @Override
        public void run() {
            while(true) {
                list.add("a");
            }
        }
    }
}

如果您多次运行此程序,则通常在获得ConcurrentModificationException 之前
就已经掌握了OutOfMemoryError

如果将其替换为CopyOnWriteArrayList,则不会出现异常(但是程序运行很慢)

请注意,这只是一个演示-好处CopyOnWriteArrayList是当读取次数 大大超过 写入次数时。



 类似资料:
  • 本文向大家介绍R vs. Python 数据分析中谁与争锋?,包括了R vs. Python 数据分析中谁与争锋?的使用技巧和注意事项,需要的朋友参考一下 当我们想要选择一种编程语言进行数据分析时,相信大多数人都会想到R和Python——但是从这两个非常强大、灵活的数据分析语言中二选一是非常困难的。 我承认我还没能从这两个数据科学家喜爱的语言中选出更好的那一个。因此,为了使事情变得有趣,本文将介绍

  • 我已经编写了一个计时器,它将测量任何多线程应用程序中特定代码的性能。在下面的计时器中,它还将用x毫秒的调用次数填充映射。我将使用这个图作为我的直方图的一部分来做进一步的分析,比如调用的百分比花费了这么多毫秒等等。 例如,这是我将使用上面的计时器类来衡量多线程应用程序中特定代码的性能的方式: 现在我的问题是,如果你看一下getDuration方法,我也会在我的地图中填充一些信息,比如花了x毫秒的调用

  • 问题内容: 我目前正在尝试Python3.7中引入的新数据类构造。我目前坚持尝试做一些父类的继承。看来参数的顺序已被我当前的方法所破坏,因此子类中的bool参数在其他参数之前传递。这导致类型错误。 当我运行此代码时,我得到了: 我该如何解决? 问题答案: 数据类组合属性的方式使您无法在基类中使用具有默认值的属性,然后在子类中使用没有默认值的属性(位置属性)。 这是因为通过从MRO的底部开始并按先见

  • 我有一个应用程序在Symfony需要发送电子邮件/通知从应用程序。由于电子邮件/通知发送过程需要时间,所以我决定将它们放入队列中,并定期处理队列。因此,我可以减少涉及电子邮件/通知分派的请求的响应时间。 处理队列的Cron作业(一个php脚本-Symfony路由)每30秒运行一次,检查是否有未发送的电子邮件/通知,如果发现,它将从队列表中获取所有数据并开始发送它们。当发送电子邮件/通知时,队列表行

  • 数据类似乎是Java中老式POJO的替代品。这些类将允许继承是可以预期的,但我看不到扩展数据类的方便方法。我需要的是这样的东西:

  • 这是我的第一个kotlin android项目,所以为愚蠢道歉。用户选择一个餐馆,用户决定为该特定餐馆添加一个思想,用户单击按钮,思想/usermeal被添加到所选餐馆的“餐食”arraylist中 数据类____ ) ----我在中间屏幕上的活动,餐厅是传入的----