Sergey Shustikov
Sergey Shustikov

Reputation: 15821

How to correctly stop thread?

I have class that represents a download task unit.

import android.os.Environment;
import android.util.Log;

import java.io.BufferedInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.URL;
import java.net.URLConnection;

/**
 * Created by Sergey Shustikov ([email protected]) at 2015.
 */
public class DownloadTask extends Thread implements DownloadActions
{

    private DownloadStateListener mListener;
    private String mDownloadLink;

    public DownloadTask(String downloadLink)
    {
        mDownloadLink = downloadLink;
    }

    @Override
    public void cancel()
    {
        interrupt();
        mListener.onDownloadCanceled(mDownloadLink);
    }

    @Override
    public void setDownloadStateChangedListener(DownloadStateListener listener)
    {
        mListener = listener;
    }

    @Override
    public void run()
    {
        int count;
        try {
            mListener.onDownloadStarted(mDownloadLink);
            URL url = new URL(mDownloadLink);
            URLConnection connection = url.openConnection();
            connection.connect();

            // this will be useful so that you can show a tipical 0-100%
            // progress bar
            int contentLength = connection.getContentLength();

            // download the file
            InputStream input = new BufferedInputStream(connection.getInputStream());

            // Output stream
            OutputStream output = new FileOutputStream(Environment.getExternalStorageDirectory().toString() + "/Download/");

            byte data[] = new byte[1024];

            long total = 0;

            while ((count = input.read(data)) != -1) {
                total += count;
                // publishing the progress....
                // After this onProgressUpdate will be called
                mListener.onDownloadProgress(mDownloadLink, (int) ((total * 100) / contentLength));

                // writing data to file
                output.write(data, 0, count);
            }

            close(connection, input, output);
            mListener.onDownloadFinished(mDownloadLink);

        } catch (Exception e) {
            Log.e("Error: ", e.getMessage());
            mListener.onDownloadFailed(mDownloadLink, new DownloadError(e.getMessage()));
        }

    }

    private synchronized void close(URLConnection connection, InputStream input, OutputStream output)
    {
        try {
            // flushing output
            if (output != null) {
                output.flush();
            }
        } catch (IOException e) {
            e.printStackTrace();
        }

        // closing streams
        try {
            // flushing output
            if (output != null) {
                output.close();
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
        try {
            // flushing output
            if (input != null) {
                input.close();
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

I need to stop downloading, clear downloaded data and close connection when i call cancel() method.

I know - there are many discussion about stop mechanism in Java.

I can't use this answer :

You can create a boolean field and check it inside run:

public class Task implements Runnable {

   private volatile boolean isRunning = true;

   public void run() {

       while (isRunning) {
       //do work
       }
   } 
   public void kill() {
         isRunning = false;
   }

}

To stop it just call

task.kill();

This should work.

because it is no operation in loop.

So how i can correctly do that?

Upvotes: 0

Views: 399

Answers (3)

Ofek Ron
Ofek Ron

Reputation: 8580

You cant interrupt a thread unless the code you let the thread run is interruptable - that is - checking for itself if it was interrupted.

EDIT In your case - something like :

final Thread cancelable = new Thread() {

            @Override
            public void run() {
                int count;
                try {
                    ...

                    while ((count = input.read(data)) != -1 && !Thread.interrupted()) {
                        total += count;
                        // publishing the progress....
                        // After this onProgressUpdate will be called
                        mListener.onDownloadProgress(mDownloadLink, (int) ((total * 100) / contentLength));

                        // writing data to file
                        output.write(data, 0, count);
                    }
                    if ( Thread.interrupted() ) {
                        mListener.onDownloadCanceled(mDownloadLink);
                    }
                    ...
                }
            }
            }
        });

and to stop the download you must call :

cancelable.interrupt();

Upvotes: 1

shobhan
shobhan

Reputation: 1518

public class Task implements Runnable {

   private boolean cancel;

   public void run() {

     try{

       while (yourCondition) {
       //do work
          if(cancel){
             throw new DownloadCancelException();
          }
       }
     }catch(DownloadCancelException e){
        //clear downloaded stuff over here
     }

   } 
   public void kill() {
         cancel = true;
   }

}

Upvotes: 0

Smutje
Smutje

Reputation: 18123

You have to interrupt your (potentially long-running) reading process:

while ((count = input.read(data)) != -1 && isRunning) {
    // perform reading
}

Upvotes: 2

Related Questions