2012-04-10 54 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