所以我在编写自己的AsyncTask类时遇到了麻烦,就像本机上运行在ThreadPoolExecutor上的系统一样。一切都很好,直到我决定实施进展的一面。进度非常类似AsyncTask
,在UI线程上调用onProgressUpdate
函数。我遇到的问题是,只要onProgressUpdate中有System.out或Log.x行,它就会无限期挂起,没有任何错误或警告。代码如下:
public abstract class Task<A, B> {
private static final Executor EXECUTOR = getExecutor();
private static final int DEFAULT_PRIORITY = Thread.MIN_PRIORITY;
private static final int DEFAULT_PROGRESS_INCREMENT = 1;
private static final Executor getExecutor() {
ThreadPoolExecutor executor = (ThreadPoolExecutor) Executors.newCachedThreadPool();
executor.setCorePoolSize(1);
executor.allowCoreThreadTimeOut(false);
// TODO set rejection handler
//executor.setRejectedExecutionHandler(new Handler());
// TODO set thread factory
executor.prestartCoreThread();
return executor;
}
public static class ExecutionListener<B> {
public void onPreExecute() {
Log.i("TASK", "Pre - Thread: " + Thread.currentThread().getId());
}
public void onPostExecute(B output) {
Log.i("TASK", "Post - Thread: " + Thread.currentThread().getId() + " - Output: " + output);
}
public void onProgressUpdate(int progress) {
Log.d("TASK", "Hello");
}
}
private Handler handler;
private ExecutionListener<B> executionListener;
private volatile int progress = 0;
private AtomicBoolean progressPublished = new AtomicBoolean(true);
private B output;
public Task() {
this.handler = new Handler();
this.executionListener = new ExecutionListener();
}
public void setExecutionListener(ExecutionListener executionListener) {
if(executionListener == null) {
this.executionListener = new ExecutionListener();
}
else {
this.executionListener = executionListener;
}
}
protected void updateProgress(int progressMade) {
Log.d("TASK", "Test");
progress += progressMade;
if(progressPublished.compareAndSet(true, false)) {
if(!handler.post(new Runnable() {
@Override
public void run() {
Log.d("TASK", new Integer(progress).toString() + " - a");
executionListener.onProgressUpdate(progress);
// Hangs below
progressPublished.lazySet(true);
Log.d("TASK", new Integer(progress).toString() + " - b");
}
})) {
Log.d("TASK", "Failed to post");
}
}
}
protected void updateProgress() {
updateProgress(DEFAULT_PROGRESS_INCREMENT);
}
protected abstract B doTask(A input);
public void execute(final A input, final int priority) {
EXECUTOR.execute(new Runnable() {
@Override
public void run() {
Thread.currentThread().setPriority(priority);
handler.post(new Runnable() {
@Override
public void run() {
executionListener.onPreExecute();
}
});
output = doTask(input);
if(!handler.post(new Runnable() {
@Override
public void run() {
Log.d("TASK", "Done");
executionListener.onPostExecute(output);
}
})) {
Log.d("TASK", "Failed to post post");
}
}
});
}
public void execute(final A input) {
execute(input, DEFAULT_PRIORITY);
}
}
ExecutionListener
只是一个类来覆盖要在UI上运行的方法,就像AsyncTask的方法一样。代码使用Runnable对象来执行doTask方法,并将更新/结果发送到ExecutionListener中的相应方法。
Thread.currentThread()
部分只是为了确保事情在我想要的线程上运行。运行一个经常调用updateProgress()
的任务时,问题只会显示出来 - 我已经尝试在onProgressUpdate()
方法中使用线程睡眠,这似乎解决了问题,尽管这显然不是一个好的解决方案。
它似乎也只有Log.x / System.out的问题 - 我不知道它们中任何一个的通话频率是否会引起这种问题。我对这个进展功能和记录感到茫然,所以任何建议都会非常感激 - 我也发现这很难解释所以请问你是否需要我澄清一切!
答案 0 :(得分:0)
结果是Thread.currentThread()。getId()出错了。删除该部分可修复所有问题。在此处跟进问题:Is Java Thread getId() thread-safe?