0

I would like to load a file into my application. The problem I'm having is that the file could take an infinite amount of time to load.
I would like to allow the user to cancel a file if they would like to stop it loading into the system. After the file has stopped loading I would like to execute code straight after in the same thread.

I wrote out a simplified example for how this could be done. My solution is by having a nested thread for the code that could load indefinitely. If the user cancels then it interrupts the thread.

public class InfiniteLoopTest {

    public static void main(String args[]) throws InterruptedException
    {

        final Thread[] innerThread = new Thread[1];

        final Thread outerThread = new Thread(new Runnable(){

            @Override
            public void run() {
                innerThread[0] = new Thread(new Runnable()
                {
                    @Override
                    public void run()
                    {   
                        try 
                        {
                            // Load in the file here (Never finishes)
                            loadFile();
                        } 
                        catch (InterruptedException e) 
                        {
                            e.printStackTrace();
                        }
                    }
                });

                innerThread[0].start();

                // Wait for the thread to complete
                try 
                {
                    innerThread[0].join();
                } 
                catch (InterruptedException e) 
                {
                    e.printStackTrace();
                }

                // Code that must always be called whether the file isn't loaded or not
                System.out.println("Do something after loading the file");
            }
        });

        outerThread.start();

        // Wait 5 seconds then simulate the user cancelling loading the file
        Thread.sleep(5000);
        innerThread[0].interrupt();
    }
}

The problem I'm having is I would like to use executor services instead of only threads and pass exceptions up if there are any issues. This means that although this solution works it will end up getting quite messy and less maintainable.

Is it possible to avoid a nested thread?

Michael
  • 3,411
  • 4
  • 25
  • 56
  • you have to break long running task... it so happens that loading file happens to a limited buffer, so you just have to check for cancellation between reads from the buffer. – diginoise Jul 12 '18 at 11:54
  • also have a look at `CompletableFuture` class which is a good abstraction of a task which you might wish to force complete before the task gets completed. – diginoise Jul 12 '18 at 11:59
  • The problem is I'm using Apache POI for files such as XLS files. Trying to decode them blocks until it is complete. Your method would work if I was just reading the files in with a buffer but the issue isn't just about reading them but also processing them. – Michael Jul 12 '18 at 12:02

2 Answers2

1

Add a boolean parameter that is accessible from both Threads and pass it to while loop. When user clicks change its value and loop will stop and continue to execute code after it.

Mladen Savić
  • 472
  • 4
  • 10
  • The `while` loop is the equivalent of an infinitely loading file. I can't change this bit of code as it is the same as calling a method called `loadFile()` or similar. It's there as an example of code loading indefinitely. – Michael Jul 12 '18 at 11:47
-1

You could use a finally {} block to avoid the nested Thread:

final Thread t = new Thread(() -> {
    try {
        loadFile();
    } catch (InterruptedException ex) {
        ex.printStackTrace();
    } finally {
        // Code that must always be called whether the file isn't loaded or not
        System.out.println("Do something after loading the file");
    }
});

t.start();

// Wait 5 seconds then simulate the user cancelling loading the file
Thread.sleep(5000);
t.interrupt();
Torsten Fehre
  • 567
  • 2
  • 7
  • What happens if during the finally another `InterruptedException` is thrown? The code I want in the finally may take some time to complete. Also I don't believe you can have an `InterruptedException` thrown if you don't have a `Thread.sleep` in the `try` block. – Michael Jul 12 '18 at 14:41
  • You mean the code in `System.out.println("Do something after loading...") can be interrupted by the user, too? And what will throw the InterruptedException? BTW: the call of t.interrupt() itself will just set an "interrupted"-flag in the thread. It is your task within the `loadFile()`-method to check if the thread was interrupted and then throw the InterruptedException. – Torsten Fehre Jul 12 '18 at 14:52
  • Does the code you have there compile? If `loadFile` doesn't throw an `InterruptedException` then it shouldn't compile. Otherwise if it can work like this then I could store a `boolean` to say that it can't be interrupted after the file is loaded. – Michael Jul 12 '18 at 14:55