【问题标题】:java - Thread IllegalThreadStateException when downloading multiple filesjava - 下载多个文件时出现线程 IllegalThreadStateException
【发布时间】:2016-08-04 16:14:17
【问题描述】:

我正在尝试多线程,并想实现一个小程序来同时下载多个文件。 我创建了一个扩展 Thread 的 FileDownloader 类。

总的来说,我的想法是创建一个包含所有相关 FileDownload 对象 (allDownloads) 的 ArrayList 和另一个名为 activeDownloads 的 ArrayList,我将活动下载的数量限制为 4。

程序下载了几个文件然后抛出这个异常。我知道在尝试再次启动线程时会抛出它。但是在下面的程序中,每次文件下载完成时,我都会中断一个线程并启动另一个线程,所以我不明白,我怎么会尝试启动 SAME Thread?

while (allDownloads.size() > 0) {
            while (activeDownloads.size() < 4) {
                if (allDownloads.iterator().hasNext()) {
                    FileDownloader d = allDownloads.iterator().next();
                    activeDownloads.add(d);
                    allDownloads.remove(d);

                }
            }
            for (int i = 0; i < activeDownloads.size(); i++) {
                FileDownloader t = activeDownloads.get(i);
                try {
                    if (!t.isRunning())
                        t.start();
                    else if (t.isFinished()) {
                        t.interrupt();
                        activeDownloads.remove(t);
                    }
                } catch (IllegalThreadStateException e) {
                    System.out.println("****Thread cannot be restarted****");
                }
            }

        }

感谢您的帮助

【问题讨论】:

  • 你能把异常信息放上去吗,在 catch 子句中添加 e.printStackTrace() 这样我们就可以确切地看到发生了什么
  • 是的:将 println 放入你的 catch 块中,甚至不打印 e 的消息,这并不比一个空的 catch 块好多少。所以,有些事情失败了,但为什么要说到底...
  • t.isRunning() 方法是什么?我不认为它是Thread api 的一部分。
  • 你能把你的FileDownloader类的代码贴出来

标签: java arrays multithreading arraylist download


【解决方案1】:

您的错误可能在这里:

if (allDownloads.iterator().hasNext()) {
    FileDownloader d = allDownloads.iterator().next();
    ...
}

您应该将 allDownloads.iterator() 的值保存在专用变量中,否则您将在每次调用时创建一个新的迭代器,然后始终获取第一个值,因此这里是同一个线程。

所以代码应该是:

Iterator<FileDownloader> it = allDownloads.iterator();
while (activeDownloads.size() < 4) {
    if (it.hasNext()) {
        FileDownloader d = it.next();
        activeDownloads.add(d);
        it.remove();

    }
}

【讨论】:

    【解决方案2】:

    您正在从 activeDownloads 中删除元素,同时对其进行迭代。尝试在 List 上向后迭代

    for (int i = activeDownloads.size()-1 ; i >=0 ; i--) {...}
    

    这样,当您从 List 中删除元素时,您的索引仍然是正确的

    【讨论】:

    • 这不是问题的根源,他当然可以在迭代容器列表时删除一个元素我看不出有什么问题!
    • 是的,但是索引将不正确。即当您删除列表的第二个元素时,第三个将变为第二个等等。因此您的下一个 get(i) 将引用一个意外元素。
    • 应该生成一个IllegalThreadStateException异常我不这么认为?
    • 否则为了避免这种情况,他不必向后迭代,如果他删除了一个元素,他只需要减少索引
    • 向后迭代比在 for 循环中修改索引更直观。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2011-03-25
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-05-18
    相关资源
    最近更新 更多