使用Runnable修复StackOverflowError递归

时间:2017-06-01 02:04:56

标签: java android recursion

我在调用此递归方法时收到StackOverflowError异常报告:

private void downloadFiles(int index) {
    if (index < totalFiles) {
        downloadSingleFile(index, new DownloadCallback() {
            @Override
            public void onSuccess(String filePath) {
                downloadFiles(index + 1);
            }
        });
    }
}

我想问一下我是否像这样使用Runnable:

int index = 0;
handler = new Handler();
Runnable runnable = new Runnable() {
    @Override
    public void run() {
        downloadFiles();
    }
};
handler.post(runnable);

private void downloadFiles() {
    if (index < totalFiles) {
        downloadSingleFile(index, new DownloadCallback() {
            @Override
            public void onSuccess(String filePath) {
                index ++;
                handler.post(runnable);
            }
        });
    }
}

这也是一个递归,抛出异常吗? 感谢

1 个答案:

答案 0 :(得分:1)

您当前使用的递归排序使得使用多个线程失败的目的。目前,您只创建一个将进入downloadFiles()的单个线程,然后递归尝试下载每个可用文件。这不是真正的多线程,它是带递归的单线程。这种方法有几个缺点。首先,您没有利用多线程并行工作的能力。其次,由于每个后续递归调用都依赖于前一个成功,所以您尝试串行下载文件。如果给定的文件下载失败,它将破坏递归链的其余部分。

更好的方法是为每个文件下载生成一个新线程。这将允许您使用多线程的功能来并行拆分任务,并且即使一个线程遇到一些问题,它也允许继续进行。

请查看以下代码段,了解如何解决问题:

public class FileDownloader implements Runnable {
    private index;

    public FileDownloader(int index) {
        this.index = index;
    }

    public void run() {
        downloadSingleFile(index, new DownloadCallback() {
            @Override
            public void onSuccess(String filePath) {
                // this may no longer be needed
            }
        });
    }
}

// use a thread pool of size 5 to handle your file downloads
ExecutorService executor = Executors.newFixedThreadPool(5);
for (int index=0; index < totalFiles; ++index) {
    Runnable r = new FileDownloader(index);
    executor.execute(r);
}

// shut down the thread pool executor and wait for it to terminate
executor.shutdown();
while (!executor.isTerminated()) {
}