2013-03-01 60 views
0

在我的Java Web應用程序中,我有一個結束大約200封電子郵件的方法。由於電子郵件服務器延遲,整個過程大約需要7分鐘。此批量電子郵件發送必須發生在用戶操作的結果中。我當然不希望用戶在轉發到下一個版本之前必須等待很長時間,而不是說Apache無論如何都不會超時,所以我試圖實現FutureTask來讓進程在單獨的線程中運行,同時繼續其餘代碼如下:使用FutureTask進行異步程序時遇到問題

Some code; 

Runnable r = (Runnable)new sendEmails(ids); 
FutureTask task = new FutureTask(r, null); 
Thread t = new Thread(task); 
t.start(); 

Some more code; 

但是,該應用程序仍在等待FutureTask完成,然後再繼續。我接受這樣的想法,即在繼續執行腳本的其餘部分的同時,這也不是在另一個線程中運行一些代碼的最佳方式。有更好的方法/我如何使這個工作?

+0

這應該不會被阻止,除非您在'More some code'塊中某個地方調用'get'任務。 – yakshaver 2013-03-01 18:14:11

+0

線程完成工作後,您是否想要執行一些操作? 「你的意思是什麼?」然而,應用程序仍然等待FutureTask在繼續之前完成?您的代碼中沒有阻止呼叫。 – 2013-03-01 18:14:48

+0

我不打電話過去,我不需要退貨。意思是說,當我調用這段代碼時,「更多的代碼」(只是將用戶轉到頁面的調用)在Runnable完成之前不會執行。 – sgd 2013-03-01 18:49:00

回答

0

它看起來像你在for循環中旋轉200多個線程。這會給機器帶來很大的負擔,並且由於每個線程分配的每個堆棧的大小,在JVM耗盡內存之前,它不會佔用太多的線程,最初會導致大量的GC和JVM鎖定,然後潛在地在足夠高的負荷下,發生碰撞。

不幸的是,這可能或不可能解釋爲什麼你的代碼正在等待FutureTasks完成。它可能似乎只是通過創建/調度如此之多的線程來等待正常的抖動;但之後它可能不會。可能還有其他的東西正在同步你的代碼,這些代碼已經被刪除掉了上面的代碼片斷。

找到隱藏在某處的技巧性同步的方法是在運行代碼時按ctrl-break(假設您從命令行運行,intellij/eclipse都有一個堆棧轉儲圖標,很方便)。這將導致出現系統中每個線程的堆棧轉儲。通過這樣做,您將能夠找到正在等待未來任務完成的用戶線程,並且會說明它正在等待哪個監視器。如果它不在等待,那麼你有一個不同的問題。例如,系統會在短時間內創建如此多的線程,以至於在短時間內出現鎖定或某些情況。

但首先我會避免過多的線程創建部分,因爲這可能會掩蓋問題。我建議使用類似於以下代碼:

ExecutorService scheduler = Executors.newCachedThreadPool() 
scheduler.submit(task) 
+0

for循環不在上面的代碼之外,它在sendEmails函數中。我已經嘗試過一些執行者,但我會嘗試你的安排,看看它是否有效。 – sgd 2013-03-01 19:36:29

+0

似乎它在繼續前等待任務完成。 – sgd 2013-03-01 19:48:44

+0

但是我收到了這個錯誤消息:java.lang.ClassCastException:my.application.CurrentClass $ sendEmails不能轉換爲java.lang.Runnable – sgd 2013-03-01 19:51:24

相關問題