由Future, FutureTask,Callable再到AsyncTask

Such as reprint, please credit: https://blog.csdn.net/dxh040431104/article/details/93329349

 

Future, FutureTask, Callable online description of a lot, I can not say here, just say some of my insights

FutureTask is a realization of the Future Runable, it can be directly used as throw Thread

Callable<Integer> callable = new Callable<Integer>() {
    @Override
    public Integer call() throws Exception {
        return null;
    }
} ;
FutureTask futureTask = new FutureTask(callable);
new Thread(futureTask).start();

FutureTask and Runable difference is that, FutureTask more return values ​​are also executed by other methods than Runable, these interfaces are defined Future, cancel, isCancelled, isDone, get

FutureTask also can be used with the thread pool Executor (such as Runable)

Callable<Integer> callable = new Callable<Integer>() {
    @Override
    public Integer call() throws Exception {
        return null;
    }
} ;
ExecutorService executorService = Executors.newCachedThreadPool();
FutureTask futureTask = new FutureTask(callable);
Future result = executorService.submit(futureTask);

or

Callable<Integer> callable = new Callable<Integer>() {
    @Override
    public Integer call() throws Exception {
        return null;
    }
} ;
ExecutorService executorService = Executors.newCachedThreadPool();
Future result = executorService.submit(callable);

From source should be able to see executorService.submit (callable) in fact finally packaged into executorService.submit (futureTask). as follows


With the above understanding we discuss AsyncTask:

private void testAsyncTask() {
    MyAsyncTask myAsyncTask = new MyAsyncTask();
    myAsyncTask.execute();
}

class MyAsyncTask extends AsyncTask<Void, Integer, Void> {

    @Override
    protected void onPreExecute() {
        super.onPreExecute();
    }

    @Override
    protected Void doInBackground(Void... voids) {
        if(isCancelled()) {
            return null;
        }
        return null;
    }

    @Override
    protected void onProgressUpdate(Integer... values) {
        super.onProgressUpdate(values);
    }

    @Override
    protected void onPostExecute(Void aVoid) {
        super.onPostExecute(aVoid);
    }
}

This is the simplest AsyncTask wording, but inside it is how to run it? Seen from execute.

@MainThread
public final AsyncTask<Params, Progress, Result> execute(Params... params) {
    return executeOnExecutor(sDefaultExecutor, params);
}
@MainThread
public final AsyncTask<Params, Progress, Result> executeOnExecutor(Executor exec,
        Params... params) {
.....................
    onPreExecute();
    exec.execute(mFuture);

    return this;
}

We saw onPreExecute is not it, that there @MainThread notes that this approach is basically to give you some UI updates in the main thread.

Here is exec.execute (mFuture); from the front you can see exec is sDefaultExecutor, then what sDefaultExecutor this is?

By the source we will find this is a executor,

private static class SerialExecutor implements Executor {
    final ArrayDeque<Runnable> mTasks = new ArrayDeque<Runnable>();
    Runnable mActive;

    public synchronized void execute(final Runnable r) {
        mTasks.offer(new Runnable() {
            public void run() {
                try {
                    r.run();
                } finally {
                    scheduleNext();
                }
            }
        });
        if (mActive == null) {
            scheduleNext();
        }
    }

    protected synchronized void scheduleNext() {
        if ((mActive = mTasks.poll()) != null) {
            THREAD_POOL_EXECUTOR.execute(mActive);
        }
    }
}

Above the red Runable r is actually a mFuture, exec.execute (mFuture) pass in here. Actually run in scheduleNext, the following is the focus THREAD_POOL_EXECUTOR what is?

public static final Executor THREAD_POOL_EXECUTOR;

static {
    ThreadPoolExecutor threadPoolExecutor = new ThreadPoolExecutor(
            CORE_POOL_SIZE, MAXIMUM_POOL_SIZE, KEEP_ALIVE_SECONDS, TimeUnit.SECONDS,
            sPoolWorkQueue, sThreadFactory);
    threadPoolExecutor.allowCoreThreadTimeOut(true);
    THREAD_POOL_EXECUTOR = threadPoolExecutor;
}

In fact, the thread pool, and speak in front of me is the same. So now we should be very clear, AsyncTask in fact, is the use of the thread pool and FutureTask to do asynchronous calls. Found a thread pool, so where AsyncTask inside FutureTask and Callable in it?

public AsyncTask(@Nullable Looper callbackLooper) {
    mHandler = callbackLooper == null || callbackLooper == Looper.getMainLooper()
        ? getMainHandler()
        : new Handler(callbackLooper);

    mWorker = new WorkerRunnable<Params, Result>() {
        public Result call() throws Exception {
            mTaskInvoked.set(true);
            Result result = null;
            try {
                Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND);
                //noinspection unchecked
                result = doInBackground(mParams);
                Binder.flushPendingCommands();
            } catch (Throwable tr) {
                mCancelled.set(true);
                throw tr;
            } finally {
                postResult(result);
            }
            return result;
        }
    };

    mFuture = new FutureTask<Result>(mWorker) {
        @Override
        protected void done() {
            try {
                postResultIfNotInvoked(get());
            } catch (InterruptedException e) {
                android.util.Log.w(LOG_TAG, e);
            } catch (ExecutionException e) {
                throw new RuntimeException("An error occurred while executing doInBackground()",
                        e.getCause());
            } catch (CancellationException e) {
                postResultIfNotInvoked(null);
            }
        }
    };
}
private static abstract class WorkerRunnable<Params, Result> implements Callable<Result> {
    Params[] mParams;
}

In the constructor of AsyncTask can be seen. mWorker is Callable, mFuture is FutureTask.

That whole process is very simple, run and run onPreExecute Callable in doInBackground, last run postResultIfNotInvoked.

private void postResultIfNotInvoked(Result result) {
    final boolean wasTaskInvoked = mTaskInvoked.get();
    if (!wasTaskInvoked) {
        postResult(result);
    }
}

postResultIfNotInvoked which the call is postResult. It is not very clear.


important point:

Because AsyncTask is performed asynchronously with the FutureTask, so some pit AsyncTask exist FutureTask there.

AsyncTask the cancel method is in fact not completely effective. We look at the following code:

public final boolean cancel(boolean mayInterruptIfRunning) {
    mCancelled.set(true);
    return mFuture.cancel(mayInterruptIfRunning);
}

Finally, it is interrupted by Thread.interrupt, but the interruption is limited, if the thread calling wait Object class (), wait (long) or wait (long, int) method, or the class join (), join (long), join (long, int), sleep (long) or sleep (long, int) method, you can be in broken, and network communications, such as blocked file read is not to be interrupted

So if the inside network requests, we can not stop off the network requested by the cancel method.

So you need to call your own isInterrupt method to determine whether the interrupt flag is set, for AsyncTask, it needs to be called in isCancelled doInBackground which to judge.

@Override
protected Void doInBackground(Void... voids) {
    if(isCancelled()) {
        return null;
    }
    return null;
}

If there is something wrong please point out thank you

 

Guess you like

Origin blog.csdn.net/dxh040431104/article/details/93329349