多线程中ArrayList上的java.util.ConcurrentModificationException
Hi在这里定义了两个线程EventThread1和OddThread2。EventThread1正在从ArrayList打印偶数,并从列表中删除相应的值。同一个OddThread2还打印同一ArrayList中的奇数以及列表中相应的删除值。 问题是,当我执行2到3次java.util.ConcurrentModificationException时,控制台上会出现异常。 即使我正在使用有效检查从列表中删除该值多线程中ArrayList上的java.util.ConcurrentModificationException,java,multithreading,arraylist,Java,Multithreading,Arraylist,Hi在这里定义了两个线程EventThread1和OddThread2。EventThread1正在从ArrayList打印偶数,并从列表中删除相应的值。同一个OddThread2还打印同一ArrayList中的奇数以及列表中相应的删除值。 问题是,当我执行2到3次java.util.ConcurrentModificationException时,控制台上会出现异常。 即使我正在使用有效检查从列表中删除该值 if (j.intValue() >= 0) { it.remove()
if (j.intValue() >= 0)
{
it.remove();
}
我知道为什么会这样,但我无法在这个项目中解决。
您能否建议我如何在以下程序中解决此异常,并给出解释
package MultiThreading;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
public class Eg2
{
public static void main(String[] args)
{
new EvenThread1();
new OddThread2();
}
}
class EvenThread1 implements Runnable
{
List<Integer> list = Services1.getNum();
EvenThread1()
{
Thread th = new Thread(this);
th.start();
}
@Override
public void run()
{
Iterator<Integer> it = list.iterator();
while (it.hasNext())
{
Integer j = (Integer) it.next();
int a = j % 2;
if (a == 0)
{
System.out.println("Even: " + j.intValue());
if (j.intValue() >= 0)
{
it.remove();
System.out.println("List Data=" + list);
}
}
}
}
}
class OddThread2 implements Runnable
{
List<Integer> list = Services1.getNum();
OddThread2()
{
Thread th = new Thread(this);
th.start();
}
@Override
public void run()
{
Iterator<Integer> it = list.iterator();
while (it.hasNext())
{
Integer j = (Integer) it.next();
int a = j % 2;
if (a != 0)
{
System.out.println("Odd: " + j.intValue());
if (j.intValue() >= 0)
{
it.remove();
System.out.println("List Data=" + list);
}
}
}
}
}
abstract class Services1
{
static List<Integer> list = new ArrayList<Integer>();
static
{
for (int i = 0; i < 20; i++)
{
list.add(i);
}
}
static public List<Integer> getNum()
{
return list;
}
}
包多线程;
导入java.util.ArrayList;
导入java.util.Iterator;
导入java.util.List;
公共类Eg2
{
公共静态void main(字符串[]args)
{
新的EvenThread1();
新的OddThread2();
}
}
类EvenThread1实现Runnable
{
List=Services1.getNum();
EvenThread1()
{
螺纹th=新螺纹(此);
th.start();
}
@凌驾
公开募捐
{
Iterator it=list.Iterator();
while(it.hasNext())
{
整数j=(整数)it.next();
int a=j%2;
如果(a==0)
{
System.out.println(“偶数:+j.intValue());
如果(j.intValue()>=0)
{
it.remove();
System.out.println(“列表数据=“+List”);
}
}
}
}
}
类OddThread2实现可运行
{
List=Services1.getNum();
OddThread2()
{
螺纹th=新螺纹(此);
th.start();
}
@凌驾
公开募捐
{
Iterator it=list.Iterator();
while(it.hasNext())
{
整数j=(整数)it.next();
int a=j%2;
如果(a!=0)
{
System.out.println(“奇数:+j.intValue());
如果(j.intValue()>=0)
{
it.remove();
System.out.println(“列表数据=“+List”);
}
}
}
}
}
抽象类服务1
{
静态列表=新的ArrayList();
静止的
{
对于(int i=0;i<20;i++)
{
列表.添加(i);
}
}
静态公共列表getNum()
{
退货清单;
}
}
静态列表=Collections.synchronizedList(新的ArrayList());
您需要像上面的代码一样同步您的列表,因为它将是并发调用。
ConcurrentLinkedQue
是一种类似列表的数据结构,支持并发操作。并且它可以返回一个报告拆分器.CONCURRENT
的拆分器。这是一个好的开始。但要使解决方案即使使用这些工具也能工作,您需要能够创建两个拆分器,一个用于偶数,另一个用于赔率,并且它们必须能够以某种方式跟踪各自的元素。泛化:返回一个Spliterator的Set
,给定实现分区策略的对象,并确保所有对象都跟踪自己的元素
严格地说,这不是不可能的。但是你不能把它从盒子里拿出来。你必须做一些有趣的(即棘手的和容易出错的)编码来实现这样的事情
玩得开心点,完成后把它放在github
或类似的地方。:-) 实际上,没有办法同时做到这一点。您需要同步对列表的访问,获取迭代器并删除偶数;然后同步对列表的访问,获取一个迭代器并删除奇数(或者反过来)。在两个线程中执行此操作没有意义,因为每个线程都需要独占访问列表。请注意,当在列表上使用迭代器时,他也需要同步,正如synchronizedList
Hi的javadoc所述,作为java编程概念,您几乎可以,但即使它不起作用,这仍然是一个例外。但是我得到了一个解决方案,我们必须通过同步块在每个线程中锁定列表对象。示例:synchronized(list){….}但是您也正确,应该也可以工作,但是这里不工作,我不知道为什么?
static List<Integer> list = Collections.synchronizedList(new ArrayList<Integer>());