Can';我从Java共享ArrayList中删除元素,同时向其中添加元素
首先,我这里没有使用迭代器 我在一个共享的ArrayList上使用了两个线程,第一个线程用于向ArrayList中添加值,另一个线程用于创建ArrayList的临时副本并对其执行一些操作,然后从原始列表中删除所有临时元素Can';我从Java共享ArrayList中删除元素,同时向其中添加元素,java,arraylist,synchronized,Java,Arraylist,Synchronized,首先,我这里没有使用迭代器 我在一个共享的ArrayList上使用了两个线程,第一个线程用于向ArrayList中添加值,另一个线程用于创建ArrayList的临时副本并对其执行一些操作,然后从原始列表中删除所有临时元素 import java.util.ArrayList; import java.util.Arrays; import java.util.List; public class ArraylistTest { public static void main(Stri
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
public class ArraylistTest {
public static void main(String...ar){
new AddingThread().start();
new RemovalThread().start();
}
}
class RemovalThread extends Thread{
static List<Integer> originalBigList = new ArrayList<>();
@Override
public void run(){
System.out.println("RemovalThread started");
while(true){
try {
sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("creating copy of originalBigList");
List<Integer> tempList = new ArrayList<>(originalBigList);
System.out.println("copied list");
//
//some operations on copied temp list
//
System.out.println("removing tempList elements after completing operations");
System.out.println("originalBigList before removing size "+originalBigList.size());
originalBigList.removeAll(tempList);
System.out.println("removed!!");
System.out.println("after size "+originalBigList.size());
}
}
}
class AddingThread extends Thread{
@Override
public void run(){
System.out.println("Adding thread started");
int ctr = 0;
while(true){
RemovalThread.originalBigList.add(ctr);
ctr++;
}
}
}
现在我的问题是,我在输出中看到,复制列表的语句被执行,从原始列表生成临时列表,但是删除语句没有执行,也没有给出任何异常,我使用的是简单的arraylist not Synchronized,为什么会这样
是否有任何内部锁定打开“移除”或“添加”操作?如果是,那么Collections.Synchronized(arraylist)的用途是什么
List<Integer> tempList = new ArrayList<>(originalBigList);
List templast=newarraylist(originalBigList);
将在列表构造器中通过originalBigList迭代来创建您的模板列表,如果AddingRead将并行运行,它将抛出ConcurrentModificationException,杀死您的RemovalThread可能您在控制台中看不到它,但它可能在那里。我建议使用CopyOnWriteArrayList作为您的原始英语
List<Integer> tempList = new ArrayList<>(originalBigList);
List templast=新ArrayList(Originabligst);
将在列表构造器中通过originalBigList迭代来创建您的模板列表,如果AddingRead将并行运行,它将抛出ConcurrentModificationException,杀死您的RemovalThread可能您在控制台中看不到它,但它可能在那里。我建议使用CopyOnWriteArrayList作为您的原始英语我发现了您的问题请查看以下代码
public static void main(String ...args){
long start = System.currentTimeMillis();
List<Integer> l1 = new ArrayList<>();
List<Integer> l2 = new ArrayList<>();
for(int i = 0 ; i < Integer.MAX_VALUE/10000;i++){
l1.add(i);
l2.add(i);
}
System.out.println(String.format("Field both arrays in %s seconds",(System.currentTimeMillis()-start)/1000) );
start = System.currentTimeMillis();
l1.removeAll(l2);
System.out.println(String.format("Removed one array from other %s seconds",(System.currentTimeMillis()-start)/1000) );
}
}
}我发现了您的问题请查看以下代码
public static void main(String ...args){
long start = System.currentTimeMillis();
List<Integer> l1 = new ArrayList<>();
List<Integer> l2 = new ArrayList<>();
for(int i = 0 ; i < Integer.MAX_VALUE/10000;i++){
l1.add(i);
l2.add(i);
}
System.out.println(String.format("Field both arrays in %s seconds",(System.currentTimeMillis()-start)/1000) );
start = System.currentTimeMillis();
l1.removeAll(l2);
System.out.println(String.format("Removed one array from other %s seconds",(System.currentTimeMillis()-start)/1000) );
}
}
}与@urag的答案类似(特别是关于O(n²)的注释),您可以通过修改
添加read
like来查看效果,因此它只添加了有限数量的项:
class AddingThread extends Thread{
@Override
public void run(){
System.out.println("Adding thread started");
int ctr = 0;
while(true){
if (ctr < 100_000) {
RemovalThread.originalBigList.add(ctr);
ctr++;
}
}
}
}
现在,将100_000
更改为1_000_000
,您将等待很长时间,只看到:
Adding thread started
RemovalThread started
creating copy of originalBigList
copied list
removing tempList elements after completing operations
originalBigList before removing size 1000000
与@urag的答案类似(特别是关于O(n²)的注释),您可以通过修改
addingread
like来查看效果,因此它只添加了有限数量的项:
class AddingThread extends Thread{
@Override
public void run(){
System.out.println("Adding thread started");
int ctr = 0;
while(true){
if (ctr < 100_000) {
RemovalThread.originalBigList.add(ctr);
ctr++;
}
}
}
}
现在,将100_000
更改为1_000_000
,您将等待很长时间,只看到:
Adding thread started
RemovalThread started
creating copy of originalBigList
copied list
removing tempList elements after completing operations
originalBigList before removing size 1000000
ArrayList不是线程安全的?2分钟内对该问题投2票?是的,这看起来不像是投票欺诈。嘿,汤姆,为什么会有-1评级,我只是问了一个有效的问题…ArrayList不是线程安全的?2分钟内对该问题投2票?是的,这看起来不像是选举舞弊。嘿,汤姆,为什么有-1评级,我只是问了一个有效的问题……我还以为它会根据Java文档给出ConcurrentModification异常,但它不会给出。我运行了几次这段代码,并且总是给出相同的输出。你怎么知道它没有呢?你没有试着将try catch放在内存中的所有块上,然后打印异常?因为,若在调试时执行此操作,它的行为可能会有所不同,我并没有放置try-catch,但若它发生,那个么JVM的运行时环境应该捕获它,并将在控制台中显示它。但事实并非如此,而且如果我使用CopyOnWriteArrayList,那么我有大量的写操作,因此每次写操作都会创建一个新的列表,我认为这是不可行的。请注意,迭代器的快速失效行为无法得到保证,因为一般来说,在存在非同步并发修改的情况下,不可能做出任何硬保证。快速失败迭代器会尽最大努力抛出ConcurrentModificationException。因此,编写依赖于此异常的正确性的程序是错误的:迭代器的快速失败行为应该只用于检测bug。“根据我提到的,我没有使用迭代器,请检查代码并尝试运行它,我从未遇到ConcurentModification异常。输出总是显示它无法执行remove命令,添加线程正在添加到originalListi我还认为它会根据Java文档给出ConcurrentModification异常,但它不会给出我运行了几次此代码,并且总是给出相同的输出。你怎么知道它没有尝试放置try catch在所有块的内部,同时打印异常?因为,若在调试时执行此操作,它的行为可能会有所不同,我并没有放置try-catch,但若它发生,那个么JVM的运行时环境应该捕获它,并将在控制台中显示它。但事实并非如此,而且如果我使用CopyOnWriteArrayList,那么我有大量的写操作,因此每次写操作都会创建一个新的列表,我认为这是不可行的。请注意,迭代器的快速失效行为无法得到保证,因为一般来说,在存在非同步并发修改的情况下,不可能做出任何硬保证。快速失败迭代器会尽最大努力抛出ConcurrentModificationException。因此,编写依赖于此异常的正确性的程序是错误的:迭代器的快速失败行为应该只用于检测bug。“根据我提到的,我没有使用迭代器,请检查代码并尝试运行它,我从未遇到ConcurentModification异常。输出总是显示它无法执行remove命令,并且添加线程正在添加到originAllistkanks Urag、Emre SevinçTkanks Urag、Emre Sevinç乐意帮助:)乐意帮助:)
Adding thread started
RemovalThread started
creating copy of originalBigList
copied list
removing tempList elements after completing operations
originalBigList before removing size 1000000