删除 CopyOnWriteArrayList 并发访问问题
CopyOnWriteArrayList concurrent access problem on removing
我正在努力寻找如何在不出现线程异常的情况下删除 CopyOnWriteAccess 的元素。
Exception in thread "Thread-3649" java.lang.ArrayIndexOutOfBoundsException: Index 4 out of bounds for length 4
at java.base/java.util.concurrent.CopyOnWriteArrayList.elementAt(CopyOnWriteArrayList.java:386)
at java.base/java.util.concurrent.CopyOnWriteArrayList.remove(CopyOnWriteArrayList.java:479)
at com.mycompany.playmatehunter.Downloader.init(Downloader.java:28)
at com.mycompany.playmatehunter.Downloader.run(Downloader.java:19)
at java.base/java.lang.Thread.run(Thread.java:834)
我有以下 下载器 class
public class Downloader extends Thread{
private CopyOnWriteArrayList<String> url_list;
private String chemin;
public Downloader( CopyOnWriteArrayList<String> l, String chemin)
{
this.url_list = l;
this.chemin = chemin;
}
public void run()
{
init();
}
public synchronized void init() // the list is already synchronized
{
if (!url_list.isEmpty())
{
int alea = (int)(Math.random()*url_list.size());
System.out.println(this.getName()+"removes the link nbr "+url_list.get(alea));
url_list.remove(alea);
}
}
}
在 main 里面:
CopyOnWriteArrayList<String> index = new CopyOnWriteArrayList( FileToList("/index/index.txt") );
while( index.size() != 0)
{
List<Thread> tg = new ArrayList<Thread>();
for(int i=0;i<7;i++)
{
Thread t=new Thread(new Downloader(index, ""));
t.start();
tg.add(t);
}
for(Thread t: tg)
t.join();
}
你知道如何摆脱 ThreadException 吗?
谢谢
您对列表的访问未同步。你有多个线程,即使 init()
方法是同步的,同步是在线程实例上,而不是在一个公共对象上,所以它是无用的。如果需要保证线程间的互斥,就得在一个公共对象上同步:
public void init() // No synchronization here
{
synchronized(url_list) { // synchronize on a common object
if (!url_list.isEmpty())
{
int alea = (int)(Math.random()*url_list.size());
System.out.println(this.getName()+"removes the link nbr "+url_list.get(alea));
url_list.remove(alea);
}
}
}
我正在努力寻找如何在不出现线程异常的情况下删除 CopyOnWriteAccess 的元素。
Exception in thread "Thread-3649" java.lang.ArrayIndexOutOfBoundsException: Index 4 out of bounds for length 4
at java.base/java.util.concurrent.CopyOnWriteArrayList.elementAt(CopyOnWriteArrayList.java:386)
at java.base/java.util.concurrent.CopyOnWriteArrayList.remove(CopyOnWriteArrayList.java:479)
at com.mycompany.playmatehunter.Downloader.init(Downloader.java:28)
at com.mycompany.playmatehunter.Downloader.run(Downloader.java:19)
at java.base/java.lang.Thread.run(Thread.java:834)
我有以下 下载器 class
public class Downloader extends Thread{
private CopyOnWriteArrayList<String> url_list;
private String chemin;
public Downloader( CopyOnWriteArrayList<String> l, String chemin)
{
this.url_list = l;
this.chemin = chemin;
}
public void run()
{
init();
}
public synchronized void init() // the list is already synchronized
{
if (!url_list.isEmpty())
{
int alea = (int)(Math.random()*url_list.size());
System.out.println(this.getName()+"removes the link nbr "+url_list.get(alea));
url_list.remove(alea);
}
}
}
在 main 里面:
CopyOnWriteArrayList<String> index = new CopyOnWriteArrayList( FileToList("/index/index.txt") );
while( index.size() != 0)
{
List<Thread> tg = new ArrayList<Thread>();
for(int i=0;i<7;i++)
{
Thread t=new Thread(new Downloader(index, ""));
t.start();
tg.add(t);
}
for(Thread t: tg)
t.join();
}
你知道如何摆脱 ThreadException 吗? 谢谢
您对列表的访问未同步。你有多个线程,即使 init()
方法是同步的,同步是在线程实例上,而不是在一个公共对象上,所以它是无用的。如果需要保证线程间的互斥,就得在一个公共对象上同步:
public void init() // No synchronization here
{
synchronized(url_list) { // synchronize on a common object
if (!url_list.isEmpty())
{
int alea = (int)(Math.random()*url_list.size());
System.out.println(this.getName()+"removes the link nbr "+url_list.get(alea));
url_list.remove(alea);
}
}
}