2012-04-10 90 views
0

我有一个网络爬虫,其中基本布局是一个管理器,它运行代理打开连接,获取内容并将其插入到数据库中。在“无限”循环线程中运行代理是错误的?

这些试剂中的每一个在一个循环中,直到用户发送一个停止信号运行在单独的线程。这些代理从经理代理处获取任务。

问题是如果在一个剂发生了异常,它不能被倒掉到接口(除非我使用一些观察者发信号通知发生了异常)。

我想,这样的设计是错误的,正确的是建立一个有限的任务,并把他们的执行人(创建任务为每个URL打开连接,获取内容或插入到数据库)。

我是对的,我目前的设计是错误的,必须改变布局?多线程使用的正确布局是什么?不同的代理在不同的工作部分执行不同的部分?

回答

4

是的,我想你应该使用Executors。如果您提交Callable类,你可以从你的蜘蛛代理抛出并检查返回Future这导致引发的作业提交,因此它可以被记录或显示给你的用户界面异常。

ExecutorService pool = Executors.newFixedThreadPool(10); 
Future<Void> future = pool.submit(new Callable<Void>() { 
    public Void call() throws Exception { 
     // your agent code goes here 
     // this can throw an exception in this block which will be re-thrown below 
     return null; 
    } 
}); 
... 
try { 
    // then the exception will be thrown here for you to catch and log 
    future.get(); 
} catch (ExecutionException e) { 
    // log the e.getCause() here 
} 
... 
pool.shutdown(); 
+0

假设这个类是Manager,我有三种类型的代理并行运行。任务按顺序完成(打开,读取和插入,每一个代理)。我需要在Manager中获得每个Executor结果的循环。但是当调用'get()'方法时执行会被阻塞,所以我需要三个管理器,每个管理器都运行一个执行器,以便在get方法被调用时不被阻塞? – 2012-04-10 16:23:46

+0

任何理由不致从一个线程@Renato调用所有3个代理?是否有理由给每个代理类型提供一个线程?鉴于他们各自完成整个任务的一部分,这似乎是不必要的复杂性。 – Gray 2012-04-10 16:26:23

+0

原因是打开连接到站点很慢(I/O),所以我有10个线程并行打开连接(示例)。当连接已经打开时,获取内容会更快,所以我只有2个fetchers用于10个开启者。如果开瓶器正在抓取,它们不会打开连接并减慢抓取速度。插入器只有一个线程,因为它是最快的操作,并且以这种方式,它将只使用一个数据库连接。如果开放程序或读取器正在插入数据库中,则必须打开每个数据库的一个数据库连接。 – 2012-04-10 16:34:47