一个简单的java多线程问题
public class Begin {
public static void main(String[] args) {
Image image = new Image();
List<String> list = new ArrayList<String>();
list.add("1.jpg");
list.add("5.jpg");
list.add("2.jpg");
list.add("7.jpg");
list.add("6.jpg");
list.add("9.jpg");
image.setUrls(list);
for (int i = 0; i < 3; i++) {
ImageDFile imageDFile = new ImageDFile(image);
imageDFile.start();
}
}
}
ImageDFile类
public class ImageDFile extends Thread {
public Image image;
public ImageDFile(Image image) {
this.image = image;
}
@Override
public void run() {
List<String> list = image.getUrls();
for (int i = 0; i < list.size(); i++) {
if (list.size() > 0) {
System.out.println(list.get(i) + "---" + Thread.currentThread().getName());
list.remove(i);
}
}
}
}
Image类就一个属性 private List<String> urls
运行的时候时不时的报错
Exception in thread "Thread-0"
java.lang.IndexOutOfBoundsException: Index: 1, Size: 1
知道肯定是多线程导致的,不知道synchronized应该加在什么位置?可否详细讲下
------解决方案--------------------List线程不安全导致,你想要得到什么样的效果
------解决方案-------------------- 觉得是 list.remove(i); 的问题,你可以先注释掉看程序可以不
------解决方案--------------------是remove的问题,但是并非是指通常意义的遍历时Remove报错。
所谓的遍历时报错,是指先吧List装到一个Iterator中, 然后这边用Iterator.next遍历,那边用List.remove时出错。
另外,我觉得LZ的遍历代码和Remove代码有很大的问题 -- 一般来说,我觉得这个遍历时希望各个线程能尽可能快的抓List的第1个img,如果抓到了就把它排除出去。
不过即便是单线程,LZ的代码也是达不到这个目的的。
假设有List中有10个img,分别是000,001,002,...,009,通常,对于单线程来讲,希望它的输出结果就是000,001,002,...,009.
不过模拟一下就可以发现,第一个输出元素是item[0],即000不假,不过此后由于Remove语句,所以List变成了[001,002,003,...,009],然后i=1,结果下一个输出是002。
再接下去是004,006,008
此外,线程的 判断数据存在+显示数据+删除数据 应当加上同步锁,否则当判断数据时有数据存在,当显示数据时系统发现该数据已经被其它线程删除了,自然会报IndexOutofRange错误。
是我的话,线程代码可能会改成
public void run() {
List<String> list = image.getUrls();
for (; list.size()>0;) {
synchronized(this){
if (list.size() > 0) {
System.out.println(list.get(0) + "---" + Thread.currentThread().getName());
list.remove(0);
}
}
}
}
------解决方案--------------------
public class ImageDFile extends Thread {
public Image image;
public ImageDFile(Image image) {
this.image = image;
}
@Override
public void run() {
synchronized (image) { // 在此处添加synchronized关键字即可
List<String> list = image.getUrls();
for (int i = 0; i < list.size(); i++) {
if (list.size() > 0) {
System.out.println(list.get(i) + "---" + Thread.currentThread().getName());