我必须下载带有文件列表的Json,然后并行下载列表中的文件。我想定期更新ProgressDialog
,所以我以这种方式实施
我开始AsyncTask
onProgressUpdate
收到2个整数,当前进度和最大进度,并更新进度条
doInBackground
ThreadPoolExecutor
LinkedBlockingQueue<Runnable>
(tpe)
FileUtils.copyURLToFile
在AsynTask中使用ThreadPoolExecutor有什么问题吗? 我正在和一位同事讨论,他们声称线程管理中可能存在问题,可能会出现僵局,这可能会给我们未来版本带来问题
这就是代码
public static void syncFiles(...)
{
PowerManager pm = (PowerManager) context.getSystemService(Context.POWER_SERVICE);
sWakelock = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, TAG);
sWakelock.acquire();
sProgress = new ProgressDialog(context);
sProgress.setCancelable(false);
sProgress.setTitle("MyTitle");
sProgress.setMessage("Sincronizzazione in corso");
sProgress.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL);
sProgress.setIndeterminate(false);
sProgress.show();
sCurrentTask = new AsyncTask<Void, Integer, Manifest>()
{
@Override
protected void onCancelled()
{
if ((sProgress != null) && sProgress.isShowing())
sProgress.dismiss();
if ((sWakelock != null) && sWakelock.isHeld())
sWakelock.release();
};
@Override
protected Manifest doInBackground(Void... params)
{
ArrayList files = getFiles(....)// download the jsonfile, and return the list of files
final String baseurl = ... // get the remote base url
final String baselocal = ... //get the local base path ;
int tot = m.size();
publishProgress(0, tot);
final int MAX_THREADS = Runtime.getRuntime().availableProcessors(); * 4;
ThreadPoolExecutor tpe = new ThreadPoolExecutor(
MAX_THREADS,
MAX_THREADS,
1,
TimeUnit.MINUTES,
new LinkedBlockingQueue<Runnable>()
);
for (final String s: files)
{
tpe.submit(new Runnable()
{
@Override
public void run()
{
try
{
URL remoteUrl = new URL(baseurl + s);
File localUrl = new File(baselocal, s);
FileUtils.copyURLToFile(remoteUrl, localUrl, 60000, 60000);
Log.w(TAG, "Downloaded " + localUrl.getAbsolutePath() + " in " + remoteUrl);
} catch (Exception e)
{
e.printStackTrace();
Log.e(TAG, "download error " + e);
// error management logic
}
}
});
}
tpe.shutdown();
int num = 0;
publishProgress(num, tot);
try
{
while (!tpe.awaitTermination(1, TimeUnit.SECONDS))
{
int n = (int) tpe.getCompletedTaskCount();
Log.w(TAG, "COUTN: " + n + "/" + tot);
if (n != num)
{
num = n;
publishProgress(num, tot);
}
}
} catch (InterruptedException e)
{
// TODO Auto-generated catch block
e.printStackTrace();
}
return m;
}
protected void onProgressUpdate(Integer... prog)
{
if (sProgress.getMax() != prog[1]) {
sProgress.setMax(prog[1]);
}
sProgress.setProgress(prog[0]);
}
@Override
protected void onPostExecute(Manifest result)
{
sWakelock.release();
sProgress.hide();
sProgress.dismiss();
// manage results
}
}.execute();
}
答案 0 :(得分:0)
如果您要检查AsyncTask的实现,那么您可以发现AsyncTask本身具有ThreadPool,因此它将在单独的线程上启动任务。实际上,当我们可以通过.execute()来启动后台任务时,此方法通常与THREAD_POOL_EXECUTOR一起使用,以允许多个任务在由AsyncTask管理的线程池上并行运行。那么为什么你需要实现另一个。
更新 阅读this中的executeOnExecutor可能会对你有所帮助......它清楚地表明,如果你允许多个任务从线程池并行运行通常不是你想要的,因为它们的操作顺序是没有定义....但在这里你想下载文件,所以我认为订单不重要,所以在我看来你可以使用它,它不会产生任何问题。