[英]Java multithreading deadlock in Connection queue
我寫了一個小的Java程序來從網站上抓取信息。 我基本上下載了一個包含本月新聞ID的Excel文件,並將它們添加到查詢表中的數據庫中。 之后,我通過請求具有先前ID的頁面作為參數來開始抓取,使用jsoup解析頁面並將信息保存到數據庫中的另一個表中。
除此ConnectionManager
類外,其他所有操作均按預期進行
public class ConnectionManager {
public static final int MAX_CONNECTIONS = 50;
private ArrayList<Runnable> mActiveThreads = new ArrayList<Runnable>();
private ArrayList<Runnable> mQueuedRunnables = new ArrayList<Runnable>();
private static ConnectionManager instance;
//Singleton
public static ConnectionManager getInstance() {
if (instance == null) {
System.out.println("Started Connection mQueuedRunnables " + new Date());
instance = new ConnectionManager();
}
return instance;
}
//Adds new Runnable to the queue
public void push(Runnable runnable) {
mQueuedRunnables.add(runnable);
if (mActiveThreads.size() < MAX_CONNECTIONS)
startNext();
}
//Starts a Thread with the next Runnable in the queue
private void startNext() {
if (!mQueuedRunnables.isEmpty()) {
Runnable next = mQueuedRunnables.get(0);
mQueuedRunnables.remove(0);
mActiveThreads.add(next);
Thread thread = new Thread(next);
thread.start();
} else if (mActiveThreads.size() == MAX_CONNECTIONS) {
System.out.println("FINISHED " + new Date());
}
}
//Callback method called when a Thread finishes its execution,
//Runnable is removed from queue and startNext() called
public void didComplete(Runnable runnable) {
synchronized(mActiveThreads) {
mActiveThreads.remove(runnable);
if (mActiveThreads.size() < MAX_CONNECTIONS)
startNext();
}
}
}
我push()
所有Runnables
每一個我需要做的連接,這是應該有50級永久性運行Threads
,直到隊列清空。 如您所見,它保留兩個Lists
:一個用於隊列,另一個用於活動Threads
。 我push()
的Runnables
只是簡單的Runnables
,它們創建HttpURLConnection
,解析HTML
並將數據插入數據庫中。
據我所知,這應該起作用,但我懷疑某個地方存在死鎖,因為在某個時刻,活動Threads
開始下降,直到停滯為止。 我一直在調試代碼,發現盡管mActiveThreads
保持為50,但JVM中的實際活動Threads
卻越來越低。
我所做的最新更改是synchronized
塊,但似乎完全沒有幫助。 有人可以指出該代碼在哪里失敗嗎? 還是如何自己找出答案? 我嘗試使用VisualVM,但可以看到Threads
數下降,但無法弄清楚為什么:-(
好吧,事實證明它根本與多線程無關。 問題在於某些連接未建立,並且從InputStream讀取有時在某些時候失敗(我想這與打開許多並發連接有關)。
一旦我使用了setConnectTimeout()和setReadTimeout(),問題就消失了。 我還將每個連接置於3個迭代循環內,因此在觸發超時的情況下,該連接將重試2次。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.