如何正确停止线程?

时间:2015-06-01 12:55:12

标签: java android multithreading

我有代表下载任务单元的类。

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 (sergey.shustikov@youshido.com) 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();
        }
    }
}

当我调用cancel()方法时,我需要停止下载,清除下载的数据并关闭连接。

我知道 - 在Java中有很多关于停止机制的讨论。

我无法使用this answer

  

您可以创建一个布尔字段并在run:

中进行检查
public class Task implements Runnable {

   private volatile boolean isRunning = true;

   public void run() {

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

}
     

要停止它,只需致电

task.kill();
     

这应该有用。

因为循环中没有操作。

那么我怎么能正确地做到这一点?

3 个答案:

答案 0 :(得分:2)

你必须打断你的(可能是长时间的)阅读过程:

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

答案 1 :(得分:1)

你不能打断一个线程,除非你让线程运行的代码是可中断的 - 即 - 如果它被中断则检查自己。

<强> 修改 在你的情况下 - 像:

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

要停止下载,您必须致电:

cancelable.interrupt();

答案 2 :(得分:0)

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

}