1

I am getting StackOverflowError exception report while calling this recursive method :

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

I want to ask if I use a Runnable like this way:

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);
            }
        });
    }
}

Will this be a recursivity as well and throw exception ? Thanks

GeniDeveloper
  • 361
  • 3
  • 18
  • Have you at least read through the stacks trace? it should easily tell you which line causing the exception. Read https://stackoverflow.com/questions/214741/what-is-a-stackoverflowerror – Amit Phaltankar Jun 01 '17 at 02:08
  • I have read it but it's telling me if my solution using runnable will fix or not. – GeniDeveloper Jun 01 '17 at 02:24

1 Answers1

1

Your current use of recursion sort of defeats the purpose of using multiple threads. Currently, you only create a single thread which will enter downloadFiles(), and will then recursively try to download every file available. This is not really multithreading, it's single threading with recursion. There are several drawbacks to this approach. First, you are not taking advantage of the ability for multiple threads to do work in parallel. Second, since each subsequent recursive call is dependent on the previous one having succeeded, you are trying to download files in serial. If a given file download were to fail, it would break the rest of the recursive chain.

A better approach would be to spawn a new thread for each file download. This would allow you to use the power of multithreading to split the task in parallel, and it also allows progress to continue even if one thread were to encounter some problems.

Have a look at the following code snippet for an idea on how to approach your problem:

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()) {
}
Tim Biegeleisen
  • 502,043
  • 27
  • 286
  • 360
  • If you don't use a limited thread pool you'll quickly exhaust thread resources if the source contains many files. – Jim Garrison Jun 01 '17 at 02:22
  • @JimGarrison I updated my answer to use a thread pool. In all honesty, I don't do much multithreaded Java work, but the OP's use of recursion was far off from what multithreading should be doing, so I thought I'd try to answer the question. – Tim Biegeleisen Jun 01 '17 at 02:26
  • Your answer is useful in term of downloading the files in parallel but doesn't answer my question, my question was : using a runnable on that way is it still a recursion or not ? – GeniDeveloper Jun 01 '17 at 02:36
  • @GeniDeveloper Yes, it is a recursion, but the point of my answer is that using recursion for downloading files might not be the best way of doing it. Why do you want to use recursion here? – Tim Biegeleisen Jun 01 '17 at 02:37
  • ok, just because downloading in parallel in android is causing the CPU to run too much that increase the heat of the phone, I thought might be better to download files one by one, in fail I can download the next file as well. – GeniDeveloper Jun 01 '17 at 02:40
  • Then just decrease the size of the thread pool, you could even use a pool with just one worker thread. I don't know what the most energy efficient way is to download a large number of files onto an Android phone, but the executor service gives you a lot of control. – Tim Biegeleisen Jun 01 '17 at 02:41