科技行者

行者学院 转型私董会 科技行者专题报道 网红大战科技行者

知识库

知识库 安全导航

至顶网软件频道Java技巧:拷贝枚举器以加强效率

Java技巧:拷贝枚举器以加强效率

  • 扫一扫
    分享文章到微信

  • 扫一扫
    关注官方公众号
    至顶头条

  当一个代码段正对集合进行枚举而另一段代码试图修改这个集合时,就会发生常见的多线程问题。解决这一问题的方法是在处理前拷贝一份枚举变量。      在撰写多线程代码时。

作者:中国IT实验室 来源:中国IT实验室 2007年9月26日

关键字: 编程 java

  • 评论
  • 分享微博
  • 分享邮件

  当一个代码段正对集合进行枚举而另一段代码试图修改这个集合时,就会发生常见的多线程问题。解决这一问题的方法是在处理前拷贝一份枚举变量。
  
  在撰写多线程代码时,你遇到过多少次下面的提示:
  Exception in thread "main" java.util.ConcurrentModificationException
  
  这个异常产生的原因有几个。一是直接对集合调用删除操作而不是在枚举器上。二是不同的线程试图对集合进行增删操作的时候。
  
  这个解决办法的第一步就是同步代码,使得你在枚举的时候其它的线程不能增删记录。但是如果每个枚举过程要进行复杂的计算或者是数据库访问的一部分的话,这个同步就会导致可怕的后果。为了减少负面影响,可以拷贝一个只读的枚举器,去掉同步,然后采用下列代码所示的方法:
  
   private List list;
   public void add(Object obj) {
   synchronized(list) {
   list.add(obj);
   }
   }
   public void perform( ) {
   Iterator iterator = null;
   synchronized(list) {
   iterator = new CopiedIterator(list.iterator( ));
   }
   while(iterator.hasNext( )) {
   // perform resource or cpu hungry work
   }
   }
  重要的是记住,CopiedIterator不是一个克隆,只是一个只读的拷贝,所以它并没有保持原有的全部功能。最重要的是,不能再调用CopiedIterator.remove方法了。CopiedIterator.remove的实现如下:
  
   public class CopiedIterator implements Iterator {
   private Iterator iterator = null;
   public CopiedIterator(Iterator itr) {
   LinkedList list = new LinkedList( );
   while(itr.hasNext( )) {
   list.add(itr.next( ));
   }
   this.iterator = list.iterator( );
   }
   public boolean hasNext( ) {
   return this.iterator.hasNext( );
   }
   public void remove( ) {
   throw new UnsupportedOperationException("This is a read-only iterator.
   ");
   }
   public Object next( ) {
   return this.iterator.next( );
   }
   }
  枚举器的只读拷贝将用在同步状态上的时间减少到最小,因此可以增强全局的效率。
  
  
  

查看本文来源

    • 评论
    • 分享微博
    • 分享邮件