Java 多线程 爬虫程序(spider)设计与实现

当spider程序访问到一个网页,必须进行以下几项基本处理:抽取网页中包含的文本;抽取网页中包含的URL,并将其区分为网页中包含的文本;抽取网页中包含的URL,并将其区分为网站内URL或网站外URL。

2.2各主要功能 模块(类)设计

2.2.1 spider类

该类为主类,继承自线程类。它本事并不做获取网页的具体工作,而是协调其他各类共同完成任务。其主要类成员及方法如下:

2.2.2 spiderworker类

该类继承线程类,进行获取网页,抽取文本,URL等实际工作。

2.2.3 urlmanager类

该类管理所获得的各种URL,利用四种URL队列来管理。

等待队列:等待刚问的URL队列,队列中的URL一经访问完便进入完成队列或不可达URL队列。运行队列:正在访问的URL队列;完成队列:已访问过的URL队列;不可达队列:不可达的URL队列,即该URL对应的文件不可访问。

2.2.4 spiderwatcher类

该类用来监视各线程的运行情况数,能确定实时的活动线程数。

2.3 SPIDER 工作过程

a 给spider程序赋予一个初始URL,加入URL等待队列。

b根据需要确定线程池大小,启动n个线程。

c查询等待队列中是否有URL,若没有,且无其他活动线程序,线程结束;若有转 d。

d从URL等待队列中取出一个URL,并移入运行对流,根据该URL去访问,并进行网页下载,抽取文本,抽取链接等工作。若网页中包含URL,则把这些URL加入等待队列;吧访问过的URL加入完成队列,转c

3.1 java中线程的生命周期

java的线程从产生到消失,可分为四个状态:

a 新建状态:线程在已被创建但尚未执行这段时间内,处于新建状态。此时,线程对象已被分配内存空间 ,起私有数据已被初始化,但没有给其分配系统资源且线程未被调度。处于此状态的线程,可以通过调用start()或stop()函数来开始线程或终止线程。

b 运行状态:处于此状态的线程,说明它已取得处理器的控制权,正在执行中。

c 不能运行状态:当线程休眠,被挂起或等待某一资源时,它便进入不能运行状态。如果休眠时间过去,或已获得等待的资源,变重新进入运行状态。

d 死状态:当线程正常终止或强行终止时,进入死状态。此时,线程放弃所拥有的所有资源。

3.2 多线程同步

当同时运行的相互独立的线程需要共享数据并且需要考虑其他线程的状态时,就需要使用一套机制使得这些线程同步,避免在争用资源时发生冲突,甚至发生死锁。java提供多种机制以实现线程同步。多数java同步是以对象锁定为中心的。java中从object对象继承来的每个对象都有一个单独的锁。由于java中的每个对象都是从object继承来的。所以Java中的每个对象都有自己的锁。这样使它在共享的线程之间可以相互协调。在java中实现线程同步的另一个方法是通过使用synchronized关键字。java使用synchronized关键字来定义程序中要求线程同步的部分。 synchronized关键字来定义程序中要求线程同步的部分。synchronized关键字实现的基本操作是把每个需要线程同步的部分定义为一个临界区,在临界去中通一时刻只有一个线程被执行。
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
长期推荐成都知名外企(英语好 C++ JAVA)
mail to:hot13399@163.com
[url]http://woshizn.iteye.com/blog/1195498[/url]
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
4 系统实现

spider程序启动时,用下列语句初始化线程,所有线程进入新建状态:

 for(int i=0;i<pool.length;i++)


建立的线程数:

 pool[i].start();


正式为了是spider程序高效地运行,spider程序的工作-访问众多的网页,被分成小的字任务,然后把这些任务分给不同的线程。这些线程相互通信以确定获得新的工作,并把没有完成的工作当作新的工作,而且我们要确保一个URL不被多个线程访问。因此,我们创建一个urlspider类来管理各种URL,各个线程共享这些url。这些url称为临界资源,任一时刻只允许一个线程拥有该资源。如2.2.3所示。该类中从等待队列中取出一个URL的操作geturl()被定义为synchronized,即同一时刻只能有一个线程从等待队列中取出URL,并把url移入运行队列。这个线程操作完后,释放它拥有的等待队列,以便其他线程有机会使用。正是以这种机制,使的n个线程同步运行。

线程进入运行状态,调用run()完成,便进入死状态,如果这样,每个线程只访问一个URL。因此,我们在spiderworker类的run()函数里设置一个循环,每循环一次,线程就查看下一个等待队列里是否有等待url,若有,则取出,访问之;若没有等待URL,还需要查看是否有其他活动的线程,若有,继续循环,否则退出循环。线程进入死状态。考虑以下情况,若循环终止条件仅为等待队列里没有URL。那么,可能会出现以下情况:在某一时刻,URL等待队列为空,一部分线程查看后没取道URL,退出运行状态。而另一部分线程正在网络上访问网页,尚未把刚获得的新的URL加入等待队列。这就造成一部分线程提早退出运行。这使程序的效率大打折扣。实验表明,启动一百个线程,运行一段时间后,往往只剩下两三个线程处于运行状态,其余全部退出运行。这时,该多线程程序几乎退化为单线程。因此,循环终止条件必须设置为等待队列为空且其余活动线程数为零。为此,我们建立spiderwacher类,来监视各个线程的运行状态。如2.2.4所示。当一个线程从等待队列获取到一个URL时,活动线程数加一,访问完URL时,活动线程数减一。这样,我们就能确保所有线程一直保持运行状态知道没有新的URL出现。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值