2010-04-30 50 views
3

我有一個非常複雜的系統(100 +線程),它需要發送電子郵件沒有阻塞。我對該問題的解決方案是實現一個名爲EmailQueueSender的類,該類在執行開始時啓動,並具有一個ScheduledExecutorService,該類每500毫秒查看一個內部隊列,如果size()> 0則清空它。什麼設計模式用於線程隊列

雖然這樣做有一個同步的靜態方法,稱爲addEmailToQueue(String[])它接受包含body,subject..etc作爲數組的電子郵件。該系統確實有效,我的其他線程可以在將郵件添加到隊列之後繼續前進,而不會阻塞,甚至擔心郵件是否成功發送......它似乎有點雜亂......或者駭人聽聞......每個程序員當他們知道自己做錯了什麼或者有更好的方法時,他們會在肚子裏感受到這種感覺。也就是說,有人可以在手腕上打我,並建議一種更有效的方法來實現這一點?

謝謝!

回答

3

如果您使用的是Java 6,那麼可以大量使用Java中的基元java.util.concurrent包。

有一個單獨的線程處理實際發送是完全正常的。我寧可使用BlockingQueue,而不是輪詢隊列,因爲您可以使用阻止take()而不是忙等待。

如果您對電子郵件是否已成功發送感興趣,則您的追加方法可能會返回Future,以便您可以在發送郵件後傳遞返回值。

而不是有一個字符串數組,我會建議創建一個(幾乎微不足道的)Java類來保存這些值。對象創作現在很便宜。

+0

正是我所需要的!已經實施並完美運作。我也改變了電子郵件到一個內部類而不是數組....謝謝你這麼多:) – Submerged 2010-04-30 17:34:38

+0

j.u.c出來在Java 5 – 2010-05-01 02:33:40

0

可能已經有一個完整的郵件包,但我可能會從Spring支持emailjob scheduling開始。爲每封郵件發送一份新工作,並讓執行者發送工作時間,並擔心需要完成多少工作。不涉及排隊。

在框架下面,Spring使用Java Mail作爲電子郵件部分,並允許您在ThreadPoolExecutor(由@Lorenzo提及)或Quartz之間進行選擇。在我看來,Quartz更好,因爲你甚至可以設置它,以便像cron作業那樣在固定的時間點(例如在午夜)啓動你的工作。使用Spring的優點是它極大地簡化了使用這些包的工作,使您的工作變得更加簡單。

0

有很多軟件包和工具可以幫助解決這個問題,但是這種在計算機科學中廣泛研究的例子的通用名稱是producer-consumer problem。有很多衆所周知的解決方案,可以被視爲「設計模式」。

1

我不確定這是否適用於您的應用程序,但聽起來像它會。 A ThreadPoolExecutor(一個ExecutorService實現)可以採用BlockingQueue作爲參數,並且您可以簡單地將新線程添加到隊列中。完成後,您只需終止ThreadPoolExecutor即可。

private BlockingQueue<Runnable> queue; 
... 
ThreadPoolExecutor executor = new ThreadPoolExecutor(10, 10, new Long(1000), 
       TimeUnit.MILLISECONDS, this.queue); 

您可以保留添加到隊列中的所有線程的計數。當你認爲你完成了(排隊是空的,也許?)簡單地比較這個

if (issuedThreads == pool.getCompletedTaskCount()) { 
     pool.shutdown(); 
    } 

如果兩個匹配,你就完成了。終止池的另一種方法是在一個循環中等待一秒鐘:

try { 
     while (!this.pool.awaitTermination(1000, TimeUnit.MILLISECONDS)); 
} catch (InterruptedException e) {//log exception...}