连接队列中的Java多线程死锁

时间:2014-03-24 04:15:26

标签: java multithreading queue deadlock

我写了一个小的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:一个用于队列,另一个用于活动ThreadsRunnablespush()只是简单Runnables,它会生成HttpURLConnection,解析HTML并将数据插入数据库。

据我所知,这应该可行,但我怀疑某处存在死锁,因为在某些时候,活动Threads开始丢失,直到它停止。我一直在调试代码,发现当mActiveThreads保持为50时,JVM中的实际活动Threads会越来越低。

我所做的最新更改是synchronized阻止,但它似乎没有任何帮助。有人能指出我代码失败的地方吗?或者如何自己找出来?我尝试了VisualVM,我可以看到Threads数字下降,但无法找出原因: - (

1 个答案:

答案 0 :(得分:0)

嗯,事实证明根本不涉及多线程。问题是某些连接没有建立,并且从某些点读取InputStream失败(我猜这与打开许多并发连接有关)。

一旦我使用了setConnectTimeout()和setReadTimeout(),问题就消失了。我还在3迭代循环中进行每个连接,因此在触发超时的情况下,连接将被重试2次。