“This is the 14th day of my participation in the Gwen Challenge in November. Check out the details: The Last Gwen Challenge in 2021.”

So what is asynchrony

Development often encounter time-consuming tasks, such as network connections, database operations, etc., if these operations are placed in the main Thread (UI Thread), it will cause the UI to freeze. Android can use Thread and Handler two asynchronous ways to solve this problem.

The difference between synchronous and asynchronous:

Network answer: 1, synchronous execution, that is, the program will be inflexible from beginning to end, time-consuming things do not execute, the program will not continue to go down, waiting for a long time, sometimes will cause the loss of response. 2. The advantage of asynchrony is that some things, especially time-consuming things, are thrown into the background to run, so that the program can continue to do its own thing and prevent the program from getting stuck and becoming unresponsive. 1. Synchronization means that the execution of two threads is related, and one thread blocks for the execution of the other thread. 2. Asynchronous means that two threads have nothing to do with each other and run their own. Answer three: 1. Synchronization refers to the communication mode in which the sender sends data and the receiver sends back a response before sending the next data packet. 2. Asynchronism refers to the communication mode in which the sender sends data and then sends the next data packet without waiting for the receiver to send back the response. The client browser cannot do anything during this period. The client browser cannot do anything during this period. Request through the event trigger -> server processing (this is browser can still do other things) -> processing finished answer five: 1, synchronization is you call me to dinner, I heard and you go to dinner; If you don't, you keep barking until I tell you you did, and then we go to dinner. 2, asynchronous is you call me, and then go to dinner, I get the news may leave immediately, or wait until work to go to dinner.Copy the code

AsyncTask

To deal with time-consuming operations, we need to write code logic in Thread and Handler respectively, which is very tedious. Therefore, Google officially helps us to encapsulate AsyncTask based on Thread and Handler.

AsyncTask uses three generic arguments: Params, Progress, and Result

Params

Represents the type of parameter used by AsyncTask to perform a task

Progress

Represents a data type that can be published periodically during background thread processing

Result

Represents the type of data returned after the task is complete

Perform a task

The execute() method that calls AsyncTask passes in arguments and executes the task. The AsyncTask calls four methods in sequence: onPreExecute doInBackground onProgressUpdate onPostExecute

onPreExecute

The onPreExecute() method’s MainThread annotation, indicating that the method is running on the MainThread, is usually used to display a progress bar

doInBackground

Will be executed immediately after the onPreExecute method, which runs in a background thread. This will take care of the time-consuming tasks. You can also call publishProgress to update the real-time task progress.

onProgressUpdate

After the publishProgress method is called, the UI thread calls this method to return progress, which can be displayed through a progress bar.

onPostExecute

This method is called by the UI thread after the doInBackground execution is complete

onCancelled

Called when the user cancels a thread operation. Called when onCancelled() is called in the main thread.

So now that you’ve seen the AsyncTask class, you’re going to see Executor

Executor

We know that thread pool is a collection of threads, thread pool centralized management threads, to achieve thread reuse, reduce resource consumption, improve response speed and so on. Threads are used to execute asynchronous tasks. A single thread is both a unit of work and an execution mechanism. Beginning in JDK1.5, to separate the unit of work from the execution mechanism, the Executor framework was created as a unified interface to create and execute tasks. Thread pools are what the Executor framework does.

The Executor interface implementation class ThreadPoolExecutor class or ScheduledThreadPoolExecutor class object, and then call the execute () method or the submit () method add tasks to the thread, The Future object is returned if there is a return value. The Callable object returns a value, so use the submit () method; Runnable can use the execute () method, as well as submit (), Simply wrap Runnable objects with callable(Runnable Task) or callable(Runnable Task, Object result) methods, Null is returned by the Callable (Runnable Task) method and result is returned by the callable(Runnable Task, Object result) method. Provenance – tongdanping

Start encapsulating AsyncTask

Define an asynchronous task executor

The complete code

public class AsyncTaskExecutor {
    
    /** * reference {@link android.os.AsyncTask}
     */
    private static final int CPU_COUNT = Runtime.getRuntime().availableProcessors();
    // We want the core pool to have at least 2 threads and at most 4 threads,
    // The CPU count is reduced by 1 to avoid saturation
    // A CPU with background work
    private static final int CORE_POOL_SIZE = Math.max(2, Math.min(CPU_COUNT - 1.4));
    private static final int MAXIMUM_POOL_SIZE = CPU_COUNT * 2 + 1;
    private static final int KEEP_ALIVE_SECONDS = 30;

    private static final ThreadFactory sThreadFactory = new ThreadFactory() {
        private final AtomicInteger mCount = new AtomicInteger(1);

        @Override
        public Thread newThread(Runnable r) {
            return new Thread(r, "AsyncTaskExecutor #"+ mCount.getAndIncrement()); }};private static final BlockingQueue<Runnable> sPoolWorkQueue =
    new LinkedBlockingQueue<>(128);

    /**
     *
     * An {@linkJava. Util. Concurrent. Can be used in parallel execution task Executor}. * /
    private static final ThreadPoolExecutor 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;
    }

    public static void execute(Runnable runnable) {
        THREAD_POOL_EXECUTOR.execute(runnable);
    }

    public staticFuture<? > submit(Runnable runnable) {return THREAD_POOL_EXECUTOR.submit(runnable);
    }

    public static <T> Future<T> submit(Runnable runnable, T result) {
        return THREAD_POOL_EXECUTOR.submit(runnable, result);
    }

    public static <T> Future<T> submit(Callable<T> callable) {
        return THREAD_POOL_EXECUTOR.submit(callable);
    }

    public static ThreadPoolExecutor executor(a){
        returnTHREAD_POOL_EXECUTOR; }}Copy the code

Sometimes, the system needs to handle so many requests with so little execution time that each request starts a new thread and the system is constantly creating and destroying threads, which can take longer to create and destroy than the thread is executing. And when there are too many threads, the extra cost of that CPU can be huge. So we have thread pools and the core problem that thread pools solve is resource management

Defining a thread pool

DefaultWorkExecutor

public class DefaultWorkExecutor  extends ThreadPoolExecutor {
    private static final int CPU_SIZE = Runtime.getRuntime().availableProcessors();
    private static final int CORE_SIZE;
    private static final int MAX_SIZE;
    private static final long KEEP_ALIVE_TIME = 1L;

    public DefaultWorkExecutor(a) {
        this(CORE_SIZE, MAX_SIZE, KEEP_ALIVE_TIME, TimeUnit.MILLISECONDS, new LinkedBlockingQueue<Runnable>());
    }

    static {
        // The number of core threads in the thread pool is the number of CPU cores plus one
        CORE_SIZE = CPU_SIZE + 1;
        // The maximum number of threads in the thread pool is the number of CPU cores
        MAX_SIZE = CPU_SIZE * 2 + 1;
    }

    private DefaultWorkExecutor(int corePoolSize,
                                int maximumPoolSize,
                                long keepAliveTime,
                                TimeUnit unit,
                                BlockingQueue<Runnable> workQueue) {
        super(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue); }}Copy the code

Finally called with a singleton executor

public class MineExecutors {
    
    
    private static volatile MineExecutors sInstance = null;

    private Handler mHandler;
    private ThreadPoolExecutor mIoExecutor;
    private ThreadPoolExecutor mAsyncExecutor;

    private MineExecutors(a) {
        mHandler = new Handler(Looper.getMainLooper());
        mIoExecutor = new DefaultWorkExecutor();
        mAsyncExecutor = AsyncTaskExecutor.executor();
    }

    private static MineExecutors instance(a) {
        if (sInstance == null) {
            synchronized (MineExecutors.class) {
                if (sInstance == null) {
                    sInstance = newMineExecutors(); }}}return sInstance;
    }

    public static ThreadPoolExecutor ioExecutor(a) {
        return instance().mIoExecutor;
    }

    public static ThreadPoolExecutor asyncExecutor(a) {
        return instance().mAsyncExecutor;
    }

    public static void executeOnUiThread(Runnable runnable) { instance().mHandler.post(runnable); }}Copy the code

Method of use

MineExecutors.asyncExecutor().execute (() -> {
  
  /** * Time-consuming task */
    
   // return to the main thread
    MineExecutors.executeOnUiThread(() -> {
        /** * refresh the UI */
    });
});
Copy the code