要求:对程序做出修改,用LinkedList代替ArrayList,并使用Iterator来循环遍历事件集。原程序比较长下面是关键的部分程序
//: mypackage/Event.java
package mypackage;
public abstract class Event {
private long eventTime;
protected final long delayTime;
public Event(long delayTime) {
this.delayTime=delayTime;
start();
}
public void start() {
eventTime=System.nanoTime()+delayTime;
}
public boolean ready() {
return System.nanoTime()>=eventTime;
}
public abstract void action();
}//: mypackage/Controller.java
package mypackage;
import java.util.*;
public class Controller {
private List<Event> eventList=new ArrayList<Event>();
public void addEvent(Event c) {
eventList.add(c);
}
public void run() {
while(eventList.size()>0)
for(Event e:new ArrayList<Event>(eventList))
if(e.ready()) {
e.action();
eventList.remove(e);
}
}
}上面的程序是正确的,运行正常。下面是我修改以后的程序,只改动Controller类里的eventList类型跟run()方法的遍历实现,可是修改后的程序出错了,想了很久想不出原因希望高手能指点一二。。修改后Controller类如下:
public class Controller {
private LinkedList<Event> eventList=new LinkedList<Event>();
Iterator<Event> it=eventList.iterator();
public void addEvent(Event c) {
eventList.add(c);
}
public void run() {
Event e;
while(eventList.size()>0)
while(it.hasNext()) {
e=it.next();
if(e.ready()) {
e.action();
it.remove();
}
}
}
}
//Iterator<Event> it=eventList.iterator();到底要放到run()方法里还是方法外我有点
//模糊不过放到run()里一样出错,希望高手能指出问题并给个简明的修改方案,小弟不胜感激!

解决方案 »

  1.   

    Iterator <Event> it=eventList.iterator();
    放到run方法里面,while(eventList.size()>0)这个循环去掉,如果此时其他地方会操作eventList,就需要在迭代的时候锁住它
      

  2.   

    //: mypackage/Controller.java
    package mypackage;
    import java.util.*;
    public class Controller {
    private LinkedList<Event> eventList=new LinkedList<Event>();
    Iterator<Event> it=eventList.iterator();
    public void addEvent(Event c) {
    eventList.add(c);
    }
    public void run() {
    Event e;
    while(eventList.size()>0)
    while(it.hasNext()) {
    e=it.next();
    if(e.ready()) {
    e.action();
    it.remove();
    }
    }
    }
    }//: mypackage/Event.java
    package mypackage;
    public abstract class Event {
    private long eventTime;
    protected final long delayTime;
    public Event(long delayTime) {
    this.delayTime=delayTime;
    start();
    }
    public void start() {
    eventTime=System.nanoTime()+delayTime;
    }
    public boolean ready() {
    return System.nanoTime()>=eventTime;
    }
    public abstract void action();
    }//: mypackage/GrrenhouseControls.java
    package mypackage;
    public class GreenhouseControls extends Controller {
    public class WaterOn extends Event {
    public WaterOn(long delayTime) {
    super(delayTime);
    }
    public void action() {
    System.out.println("Greenhouse water is on");
    }
    }
    public class WaterOff extends Event {
    public WaterOff(long delayTime) {
    super(delayTime);
    }
    public void action() {
    System.out.println("Greenhouse water is off");
    }
    }
    public class Bell extends Event {
    public Bell(long delayTime) {
    super(delayTime);
    }
    public void action() {
    addEvent(new Bell(delayTime));
    System.out.println("Bint!");
    }
    }
    public class Restart extends Event {
    private Event[] eventList;
    public Restart(long delayTime,Event[] eventList) {
    super(delayTime);
    this.eventList=eventList;
    for(Event e:eventList)
    addEvent(e);
    }
    public void action() {
    for(Event e:eventList) {
    e.start();
    addEvent(e);
    }
    start();
    addEvent(this);
    System.out.println("Restarting system");
    }
    }
    public static class Terminate extends Event {
    public Terminate(long delayTime) {
    super(delayTime);
    }
    public void action() {
    System.out.println("Terminating");
    System.exit(0);
    }
    }
    }//: main.GreenhouseController.java
    package main;
    import mypackage.*;
    public class GreenhouseController {
    public static void main(String[] args) {
    GreenhouseControls gc=new GreenhouseControls();
    gc.addEvent(gc.new Bell(900));
    Event[] eventList={
    gc.new WaterOn(600),
    gc.new WaterOff(800),
    };
    gc.addEvent(gc.new Restart(2000,eventList));
    if(args.length==1)
    gc.addEvent(new GreenhouseControls.Terminate(new Integer(args[0])));
    gc.run();
    System.out.println("end");
    }
    }如果把Controller类改成题目中讲的正确的代码,程序可以正常运行,不过我换用Iterator来遍历就会报错。。运行后信息如下:
    Exception in thread "main" java.util.ConcurrentModificationException
    at java.util.LinkedList$ListItr.checkForComodification(Unknown Source)
    at java.util.LinkedList$ListItr.remove(Unknown Source)
    at mypackage.Controller.run(Controller.java:17)
    at main.GreenhouseController.main(GreenhouseController.java:15)
    Bint!
      

  3.   

    //: mypackage/Controller.java
    package mypackage;
    import java.util.*;
    public class Controller {
    private LinkedList<Event> eventList=new LinkedList<Event>();
    Iterator<Event> it=eventList.iterator();
    public void addEvent(Event c) {
    eventList.add(c);
    }
    public void run() {
    Event e;
    while(eventList.size()>0)
    while(it.hasNext()) {
    e=it.next();
    if(e.ready()) {
    e.action();
    it.remove();
    }
    }
    }
    }//: mypackage/Event.java
    package mypackage;
    public abstract class Event {
    private long eventTime;
    protected final long delayTime;
    public Event(long delayTime) {
    this.delayTime=delayTime;
    start();
    }
    public void start() {
    eventTime=System.nanoTime()+delayTime;
    }
    public boolean ready() {
    return System.nanoTime()>=eventTime;
    }
    public abstract void action();
    }//: mypackage/GrrenhouseControls.java
    package mypackage;
    public class GreenhouseControls extends Controller {
    public class WaterOn extends Event {
    public WaterOn(long delayTime) {
    super(delayTime);
    }
    public void action() {
    System.out.println("Greenhouse water is on");
    }
    }
    public class WaterOff extends Event {
    public WaterOff(long delayTime) {
    super(delayTime);
    }
    public void action() {
    System.out.println("Greenhouse water is off");
    }
    }
    public class Bell extends Event {
    public Bell(long delayTime) {
    super(delayTime);
    }
    public void action() {
    addEvent(new Bell(delayTime));
    System.out.println("Bint!");
    }
    }
    public class Restart extends Event {
    private Event[] eventList;
    public Restart(long delayTime,Event[] eventList) {
    super(delayTime);
    this.eventList=eventList;
    for(Event e:eventList)
    addEvent(e);
    }
    public void action() {
    for(Event e:eventList) {
    e.start();
    addEvent(e);
    }
    start();
    addEvent(this);
    System.out.println("Restarting system");
    }
    }
    public static class Terminate extends Event {
    public Terminate(long delayTime) {
    super(delayTime);
    }
    public void action() {
    System.out.println("Terminating");
    System.exit(0);
    }
    }
    }//: main.GreenhouseController.java
    package main;
    import mypackage.*;
    public class GreenhouseController {
    public static void main(String[] args) {
    GreenhouseControls gc=new GreenhouseControls();
    gc.addEvent(gc.new Bell(900));
    Event[] eventList={
    gc.new WaterOn(600),
    gc.new WaterOff(800),
    };
    gc.addEvent(gc.new Restart(2000,eventList));
    if(args.length==1)
    gc.addEvent(new GreenhouseControls.Terminate(new Integer(args[0])));
    gc.run();
    System.out.println("end");
    }
    }如果把Controller类改成题目中讲的正确的代码,程序可以正常运行,不过我换用Iterator来遍历就会报错。。运行后信息如下:
    Exception in thread "main" java.util.ConcurrentModificationException
    at java.util.LinkedList$ListItr.checkForComodification(Unknown Source)
    at java.util.LinkedList$ListItr.remove(Unknown Source)
    at mypackage.Controller.run(Controller.java:17)
    at main.GreenhouseController.main(GreenhouseController.java:15)
    Bint!
      

  4.   

    Iterator不是这样用的吧,我改了一下你的代码,不知道你为什么不按开始那样遍历
    public class Controller {
    private List<Event> eventList = new ArrayList<Event>(); public void addEvent(Event c) {
    eventList.add(c);
    } public void run() {
    while (eventList.size() > 0) {
    for (Iterator<Event> it = eventList.iterator(); it.hasNext();) {
    Event e = it.next();
    if (e.ready()) {
    e.action();
    eventList.remove(e);
    }
    } }
    }
    }PS:楼主最好把代码写在代码块理
      

  5.   

    感觉这样写有点奇怪Iterator本来就有remove方法怎么不用……因为要掌握Iterator的用法所以要改```嗯下次会写到代码块里去的`````
      

  6.   

    回复bobskay :  还是有警告。。
      

  7.   


    //: mypackage/Controller.java
    package mypackage;
    import java.util.*;
    public class Controller {
    private LinkedList<Event> eventList=new LinkedList<Event>();
    Iterator<Event> it=eventList.iterator();
    public void addEvent(Event c) {
    eventList.add(c);
    }
    public void run() {
    Event e;
    while(eventList.size()>0)
    while(it.hasNext()) {
    e=it.next();
    if(e.ready()) {
    e.action();
    it.remove();
    }
    }
    }
    }//: mypackage/Event.java
    package mypackage;
    public abstract class Event {
    private long eventTime;
    protected final long delayTime;
    public Event(long delayTime) {
    this.delayTime=delayTime;
    start();
    }
    public void start() {
    eventTime=System.nanoTime()+delayTime;
    }
    public boolean ready() {
    return System.nanoTime()>=eventTime;
    }
    public abstract void action();
    }//: mypackage/GrrenhouseControls.java
    package mypackage;
    public class GreenhouseControls extends Controller {
    public class WaterOn extends Event {
    public WaterOn(long delayTime) {
    super(delayTime);
    }
    public void action() {
    System.out.println("Greenhouse water is on");
    }
    }
    public class WaterOff extends Event {
    public WaterOff(long delayTime) {
    super(delayTime);
    }
    public void action() {
    System.out.println("Greenhouse water is off");
    }
    }
    public class Bell extends Event {
    public Bell(long delayTime) {
    super(delayTime);
    }
    public void action() {
    addEvent(new Bell(delayTime));
    System.out.println("Bint!");
    }
    }
    public class Restart extends Event {
    private Event[] eventList;
    public Restart(long delayTime,Event[] eventList) {
    super(delayTime);
    this.eventList=eventList;
    for(Event e:eventList)
    addEvent(e);
    }
    public void action() {
    for(Event e:eventList) {
    e.start();
    addEvent(e);
    }
    start();
    addEvent(this);
    System.out.println("Restarting system");
    }
    }
    public static class Terminate extends Event {
    public Terminate(long delayTime) {
    super(delayTime);
    }
    public void action() {
    System.out.println("Terminating");
    System.exit(0);
    }
    }
    }//: main.GreenhouseController.java
    package main;
    import mypackage.*;
    public class GreenhouseController {
    public static void main(String[] args) {
    GreenhouseControls gc=new GreenhouseControls();
    gc.addEvent(gc.new Bell(900));
    Event[] eventList={
    gc.new WaterOn(600),
    gc.new WaterOff(800),
    };
    gc.addEvent(gc.new Restart(2000,eventList));
    if(args.length==1)
    gc.addEvent(new GreenhouseControls.Terminate(new Integer(args[0])));
    gc.run();
    System.out.println("end");
    }
    } 如果把Controller类改成题目中讲的正确的代码,程序可以正常运行,不过我换用Iterator来遍历就会报错。。运行后信息如下:
    Exception in thread "main" java.util.ConcurrentModificationException
    at java.util.LinkedList$ListItr.checkForComodification(Unknown Source)
    at java.util.LinkedList$ListItr.remove(Unknown Source)
    at mypackage.Controller.run(Controller.java:17)
    at main.GreenhouseController.main(GreenhouseController.java:15)
    Bint!
      

  8.   

    答:主个错误:java.util.ConcurrentModificationException 我真是太熟悉了,是使用iterator()不当最常见的错误.
    初步看了你的代码,问题的根源是在Controller 类中run()代码的此处:
    if(e.ready()) {
        e.action();//此处可能会向链表中add结点(注意:不是通过it遍历器来add(..)的!)
        it.remove();//此处又从链表中删除当前结点
                    }
    显然楼主对究竟怎样正确使用it遍历器还不是很清楚.
    现在你的代码已经这样了,如果要以最少代码来修改(不影响程序大的结构),则代码可修改为(保证成功):
    将:while(it.hasNext()) {
                    e=it.next();
                    if(e.ready()) {
                        e.action();
                        it.remove();
                    }
                }改为:
    while(it.hasNext()) { 
    e=it.next(); 
    if(e.ready()) { 
    it.remove(); 
    int len=eventList.size();
    e.action(); 
    if(len!=eventList.size()) it=eventList.iterator();  
           } //if
    } //while
      

  9.   

    楼上的代码貌似还是有错误!
    楼主的代码异常主要是由于Iterator的remove方法报的,楼主的集合是想删除一个再增加一个,形成了死循环。不停的删除增加。可以集合链表中的对象的地址是改变了。删除的对象和重新生成的对象的地址是不一样的。迭代器remove的之前,集合链表发生了变化,而迭代器还是指向原来的集合链表地址,就会发生不同步的异常。所以尽量不要再迭代器迭代的时候修改集合中的数据,如果要修改,请使用循环。楼主的错误有二1.迭代器声明成全局的,首先就造成了迭代器的数据与集合不同步,因为集合是要发生变化的,必须是在变化后再进行迭代器的定向。
    2.集合迭代的时候最好不要进行迭代删除的操作。如果进行删除操作,那么就不要在删除以后或者删除之前添加新的对象经集合中。对于第二个错误,楼主可以把action方法中的添加代码注释掉,然后运行一下看看。建议:请使用原来的循环代码。否则请使用观察者模式监听集合的变化,一旦有变化,则让Iterator的对象重新指向新集合的iterator。
      

  10.   

    高高手啊!!!上面的解释实在简练关键的是说中了要害……这问题想了很久后来模模糊糊觉得是action()方法里修改类组长度弄出的问题。。不过怎么改都改不好呵呵。。又学到了谢谢!!!
      

  11.   

    已经验证过了,12楼 jiangnaisong 的回复是完全正确的。。