Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/358.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

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/multithreading/4.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制作列表的副本是线程安全的吗?_Java_Multithreading_List_Concurrency - Fatal编程技术网

Java制作列表的副本是线程安全的吗?

Java制作列表的副本是线程安全的吗?,java,multithreading,list,concurrency,Java,Multithreading,List,Concurrency,我在Java应用程序中运行多个线程,所有线程都需要访问同一个列表。但是,实际上只有一个线程需要插入/删除/更改列表,其他线程只需要访问它 在其他线程中,我想制作一份列表的副本,以便在需要阅读时使用,但是是否有任何方法可以以线程安全的方式执行此操作?如果我有一种方法,一个元素一个元素地复制列表,而列表发生了变化,那会把它搞砸的,不是吗 编辑: 列表不会经常从中删除,所以如果我只是正常复制它并捕获异常,它会工作吗?如果列表在拷贝的中间增加了,我就错过了,这对功能不会有什么影响。 Use Collec

我在Java应用程序中运行多个线程,所有线程都需要访问同一个列表。但是,实际上只有一个线程需要插入/删除/更改列表,其他线程只需要访问它

在其他线程中,我想制作一份列表的副本,以便在需要阅读时使用,但是是否有任何方法可以以线程安全的方式执行此操作?如果我有一种方法,一个元素一个元素地复制列表,而列表发生了变化,那会把它搞砸的,不是吗

编辑:

列表不会经常从中删除,所以如果我只是正常复制它并捕获异常,它会工作吗?如果列表在拷贝的中间增加了,我就错过了,这对功能

不会有什么影响。
Use Collections.synchronizedList().
例如:

Collections.synchronizedList(new ArrayList<YourClassNameHere>())
Collections.synchronizedList(新的ArrayList())

您可以使用
CopyOnWriteArrayList
实现您的目的

CopyOnWriteArrayList
是Java 5并发API中引入的一个并发集合类,以及它在Java中流行的同类
ConcurrentHashMap

顾名思义,CopyOnWriteArrayList创建基础文件的副本 带有每个变异操作的ArrayList,例如添加或设置。正常地 CopyOnWriteArrayList非常昂贵,因为它涉及昂贵的 每次写操作都要进行数组复制,但如果 列出迭代次数多于变异次数的列表,例如,你最需要 迭代ArrayList,不要经常修改它


使用此集合,您不应该每次都创建一个新实例。你应该只有一个这样的对象,它会工作。

嗯,所以我想你要找的是CopyOnWriteArrayList

CopyOnWriteArrayList-ArrayList的一种线程安全变体,其中所有变异操作(添加、设置等)都是通过创建基础数组的新副本来实现的


Ref:

您可以使用线程安全的
CopyOnWriteArrayList
,但它会在每个更新过程中创建一个新的


或者,您可以使用readWriteLock,以便在更新使用时,没有人可以读取,而多个线程可以同时读取。

根据您的具体使用情况,您可能会受益于以下其中之一:

  • 如果您真的不需要随机访问,请使用。不需要显式同步
  • 如果写操作不需要随机访问,而只需要读操作,请使用ConcurrentLinkedQueue进行写操作,并不时将其复制到列表中。如果对队列进行了更改(在单独的线程中),请将此列表提供给“读卡器”。不需要显式同步;提供“读取”视图
  • 由于您的写入来自一个线程,因此前一个线程可以处理两个列表(例如,写入线程会不时将其复制到“阅读视图”)。但是,请注意,如果使用ArrayList实现并要求对写入进行随机访问,则会看到内存区域的恒定副本,即使在没有过度同步的情况下也不太好。此选项要求在复制期间进行同步
  • 如果您不关心排序并且想要O(1)性能,或者如果您确实需要排序并且对O(logN)性能满意,请使用映射。不需要显式同步

  • 我决定通过使用一个单独的线程来处理该线程来解决这个问题,如果其他线程想要写入列表或从列表中获取,则可以使用
    BlockingQueue
    提交给它们。如果他们想要写入列表,它会提交一个包含他们想要写入的内容的对象,如果他们想要读取,它会提交一个
    未来
    ,具有列表的线程将填充

    可能会有用,而不是每次所有读取线程都需要读取列表时制作副本,当单个编写器更改列表时,可能会更有效地制作副本。这就是CopyOnWriteArrayList的策略。您也可以使用ReadWriteLock。我查找了CopyOnWriteArrayList,但我使用的列表将经常写入,因此似乎效率有点低您确定每次写入时复制列表的效率会降低吗,而不是像你愿意的那样在每次读取时复制它?大致说来,写入速率与读取速率大致相同,所以我想它可能会起作用。我将对它进行基准测试,看看它是否足够快。我正在做一个实时游戏,所以速度对我来说很重要。同时也可能会有数百个这样的列表,不会有太大的变化。在列表上迭代时,仍然需要显式同步。