首页 | 互联网 | IT动态 | IT培训 | Cisco | Windows | Linux | Java | .Net | Oracle | 软件测试 | C/C++ | 嵌入式开发 | 存储世界 | 服务器
网络设备 | IDC | 安全 | 求职招聘 | 数字网校 | 网页设计 | 平面设计 | 技术专题 | 电子书下载 | 教学视频 | 源码下载 | 搜索 | 博客 | 论坛
中国IT实验室Linux频道
中国IT教育
Google
首页 资讯动态 认证考试 新手入门 核心技术 高级技术 J2EE J2ME Java&XML 开源技术 其他技术 RSS订阅 论坛 专题
您现在的位置: 中国IT实验室 >> Java >> 开源技术 >> Spring >> 正文

Heritrix的多线程ToeThread和ToePool

    想要更有效更快速的抓取网页内容,则必须采用多线程。Heritrix中提供了一个标准的线程池ToePool,它用于管理所有的抓取线程。 ToePool和ToeThread都位于org.archive.crawler.framework包中。前面已经说过ToePool的初始化,是在CrawlController的initialize()方法中完成的。来看一下ToePool以及ToeThread是如何被初始化的。以下代码是在CrawlController中用于对ToePool进行初始化的。
    构造函数 toePool = new ToePool(this);
    // 按order.xml中的配置,实例化并启动线程
    toePool.setSize(order.getMaxToes()); ToePool的构造函数很简单,如下所示 public ToePool(CrawlController c) {
     super("ToeThreads");
     this.controller = c;
    } 它仅仅是调用了父类java.lang.ThreadGroup的构造函数,同时,将注入的CrawlController赋给类变量。这样,便建立起了一个线程池的实例了。但是,那些真正的工作线程又是如何建立的呢?
    下面来看一下线程池中的setSize(int)方法。从名称上看,这个方法很像是一个普通的赋值方法,但实际上,它并不是那么简单。 public void setSize(int newsize)
    {
     targetSize = newsize;
     int difference = newsize - getToeCount();

     // 如果发现线程池中的实际线程数量小于应有的数量
     // 则启动新的线程
     if (difference > 0) {
          for(int i = 1; i <= difference; i++) {
           // 启动新线程
              startNewThread();
      }
     }
     // 如果线程池中的线程数量已经达到需要
     else
     {

          int retainedToes = targetSize;
          // 将线程池中的线程管理起来放入数组中
          Thread[] toes = this.getToes();

          // 循环去除多余的线程
          for (int i = 0; i < toes.length ; i++) {
              if(!(toes[i] instanceof ToeThread)) {
                   continue;
              }
              retainedToes--;
              if (retainedToes>=0) {
                   continue;
              }
              ToeThread tt = (ToeThread)toes[i];
              tt.retire();
          }
     }
    }

    // 用于取得所有属于当前线程池的线程
    private Thread[] getToes()
    {
     Thread[] toes = new Thread[activeCount()+10];
     // 由于ToePool继承自java.lang.ThreadGroup类
     // 因此当调用enumerate(Thread[] toes)方法时,
     // 实际上是将所有该ThreadGroup中开辟的线程放入
     // toes这个数组中,以备后面的管理
     this.enumerate(toes);
     return toes;
    }

    // 开启一个新线程
    private synchronized void startNewThread()
    {
     ToeThread newThread = new ToeThread(this, nextSerialNumber++);
     newThread.setPriority(DEFAULT_TOE_PRIORITY);
     newThread.start();
    } 通过上面的代码可以得出这样的结论:线程池本身在创建的时候,并没有任何活动的线程实例,只有当它的setSize方法被调用时,才有可能创建新线程;如果当setSize方法被调用多次而传入不同的参数时,线程池会根据参数里所设定的值的大小,来决定池中所管理线程数量的增减。

[1] [2] 下一页

【责编:Ken】

中国IT教育

相关产品和培训
文章评论
 友情推荐链接
 认证培训
 专题推荐

 ·关于Java框架技术专题
 ·XML全攻略技术专题
 ·JAVA开源技术介绍专题
 ·Java嵌入式开发之J2ME技术专题
 ·超前体验 Oracle 11g的5个新特性…
 ·揭密使用VB.NET的五个实用技巧
 ·Oracle和SQL Server常用函数对比专题…
 ·展现C#世界 C#程序设计专题…
 ·Java入门 Tomcat的配置技巧精华专题…
 ·Oracle RMAN物理备份技术详解…
 今日更新
 社区讨论
 博客论点
 频道精选
 Java 频道导航