为什么在我尝试关闭线程后,它们仍然保持活动状态?

3

我的课程具有以下功能:https://codeshare.io/kvze0

public void startFtp(String address, int port, String username, String password, String filepath, String file)
{
    //...parsing parameter to class variables
    try {
        while (download) {
            downloadAndBroadcast();
        }
    } catch (Exception e){
        Log.d(TAG, "startFtp disconnected or fails");
        e.printStackTrace();
    }
}

private void downloadAndBroadcast() {
    beginTime = System.currentTimeMillis();
    try {
        URL url = new URL("http://" + serverAddress + "/" + serverFile);
        URLConnection urlConnection = url.openConnection();
        urlConnection.connect();
        inputStream = new BufferedInputStream(url.openStream());
        long difference;
        byte data[] = new byte[4094];
        int count;
        while ((count = inputStream.read(data)) != -1 && download) {
            downloadCount += count;
            long stoptime = System.currentTimeMillis();
            difference = stoptime - beginTime;
            if (difference > 1000 && download) {
                currentSpeed = downloadCount / (difference / 1000L);
                averageSpeed = (averageSpeed + currentSpeed) / 2;
                broadcastSpeed();
                downloadCount = 0; 
                beginTime = stoptime;
            }
        }
        clearInputStream();
    } catch (Exception e) {
        Log.d(TAG, "FAIL");
        e.printStackTrace();
    } finally {
        clearInputStream();
        Log.d(TAG, "downloadAndBroadcast: finally");
    }
}


private void broadcastSpeed() {
    Log.d(TAG, "broadcastSpeed: ");
    toMainActivityIntent = new Intent(Constants.BROADCAST_SPEED)
            .addCategory(Intent.CATEGORY_DEFAULT)
            .putExtra("speed", averageSpeed)
            .putExtra("thread", String.valueOf(Thread.currentThread().getId()));

    downloadService.sendBroadcast(toMainActivityIntent); //send to main activity, in main activity, there is a listener that analyzes Broadcast and Intent
}
private void clearInputStream() {
    if (inputStream != null) {
        try {
            inputStream.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

public void stopDownload() {
    Log.d(TAG, "stopDownload: ");
    download = false;
}

我调用 stopDownload() 方法来停止线程。之后,我记录我的ThreadPoolExecutor以查看线程的状态:

[Shutting down, pool size = 4, active threads = 4, queued tasks = 0, completed tasks = 0]

我的线程是如何变为活动状态的?提前感谢。

如何启动一个线程:

    int NUMBER_OF_CORES = Runtime.getRuntime().availableProcessors();

    executor = new ThreadPoolExecutor(
            NUMBER_OF_CORES * 2,
            NUMBER_OF_CORES * 2,
            60L,
            TimeUnit.SECONDS,
            new LinkedBlockingQueue<Runnable>()
    );
    executor.execute(new Runnable() {
        public void run() {
            FTPDownloader ftpDownloader = new FTPDownloader(downloadService);
            ftpDownloader.startFtp(server.getServer(), server.getPort(), server.getUser(), server.getPass(), server.getPath(), server.getFiledl());
            if (Thread.interrupted()) {
                Log.d(TAG, "run: ");
                ftpDownloader.stopDownload();
            }
        }
    });

我调用 executor.shutdownNow(); 关闭我的线程:

private class MainActivityReceiver extends BroadcastReceiver {
    @Override
    public void onReceive(Context context, Intent intent) {
            executor.shutdownNow();       
    }
}

我猜你最好使用AsyncTask。但无论如何 - 我看不到对shutdownNow()的调用,也不知道它应该如何调用stopDownload - Fildor
@Fildor 调用 shutDownNow() 函数被放在另一个函数中执行。 - phuwin
我以为我找到了答案,但是后来发现是错的... 你能确认下载标志确实设置为false吗?我不相信。 - Fildor
哦,你在问题中写道:“我调用stopDownload()来停止线程”,这是正确的吗?你是调用stopDownload还是关闭Executor? - Fildor
@Fildor 我刚刚查看了我的日志。你说的 stopDownload() 没有被调用是正确的。我原以为当调用 shutDownNow() 时,它会中断池中的所有线程。这里提到了:https://dev59.com/5mUo5IYBdhLWcg3wnwj2 - phuwin
1
是的,确实会有这种情况。但是你在downloadAndBroadcast函数内捕获InterruptedException异常时将重置中断状态。然后在startFTP函数中它将继续循环,因为下载仍处于真实状态。不过应该打印出堆栈跟踪信息。你可以在catch(Exception)之前添加一个带有catch(InterruptedException)的catch块,在其中简单地设置download=false; - Fildor
1个回答

1
尝试以下步骤:

删除以下行:

if (Thread.interrupted()) {
            Log.d(TAG, "run: ");
            ftpDownloader.stopDownload();
        }

downloadAndBroadcast函数中,在} catch (Exception e) {之前添加以下内容。
} catch (InterruptedException ie) {
    // catching IE will reset interrupted status. So just clear the flag.
    download = false;
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接