A quote.
Multithreaded asynchronous processing of tasks is often encountered in development, but the use of newThread to create a single thread to handle multiple threaded tasks because of the frequent creation and destruction of threads occupy a large number of resources, and thus loss of application performance.
Of course, Google officials have long been aware of this, so there are five common thread pools available for developers to use, but developers can also create their own thread pools to suit their business needs.
Here are five common thread pools in Android: FixedThreadPool, CachedThreadPool, ScheduledThreadPool, SingleThreadExecutor, SingleThreadScheduledExecutor.
Five common thread pools in Android
ExecutorService is a class that Java provides for managing thread pools, controlling the number of threads, and reusing thread functions.
1.FixedThreadPool
FixedThreadPool, which has the same core and maximum number of threads, can be thought of as a fixed number of threads pool;
Public static void testFixedThreadPool() {// Create a fixed number of thread pools for reuse; ExecutorService ExecutorService = Executors.newFixedThreadPool(3); for (int i = 0; i < 10; i++) { final int index = i; Executorservice.execute (new Runnable() {public void run() {try {// Print out the threads that are executing Log.d(TAG, thread.currentThread ().getName()+ "being executed, "+ index+" times "); Thread.sleep(2000); } catch (InterruptedException e) { e.printStackTrace(); }}}); }}Copy the code
Output Log:
The 2021-08-07 15:19:44. 959, 26761-26795 / D/ThreadPoolUtil: Pool-1-thread-1 is being executed for the 0th time 2021-08-07 15:19:44.959 26761-26797/ D/ThreadPoolUtil: Pool-1-thread-3 is being executed, 2nd time 2021-08-07 15:19:44.959 26761-26796/ D/ThreadPoolUtil: Pool-1-thread-2 is being executed for the first time 2021-08-07 15:19:46.962 26761-26795/ D/ThreadPoolUtil: 2021-08-07 15:19:46.962 26761-26797/ D/ThreadPoolUtil: 2021-08-07 15:19:46.962 26761-26796/ D/ThreadPoolUtil: 2021-08-07 15:19:48.963 26761-26796/ D/ThreadPoolUtil: 2021-08-07 15:19:48.965 26761-26797/ D/ThreadPoolUtil: Pool-1-thread-3 is being executed for the seventh time 2021-08-07 15:19:48.965 26761-26795/ D/ThreadPoolUtil: - the thread pool - 1-1 is implemented, 8 times the 2021-08-07 15:19:50. 964, 26761-26796 / D/ThreadPoolUtil: - thread pool - 1-2 are implemented, 9 timesCopy the code
By looking at the log information analysis, pay attention to the log printing time, every time the output 3 log information, and at the same time perform three threads are not the same, we set up corresponding core number of threads and the maximum number of threads Executors. NewFixedThreadPool (3),.
NewFixedThreadPool: newFixedThreadPool: newFixedThreadPool: newFixedThreadPool: newFixedThreadPool: newFixedThreadPool: newFixedThreadPool: newFixedThreadPool: newFixedThreadPool: newFixedThreadPool:
public static ExecutorService newFixedThreadPool(int nThreads) {
return new ThreadPoolExecutor(nThreads, nThreads,
0L, TimeUnit.MILLISECONDS,
new LinkedBlockingQueue<Runnable>());
}
Copy the code
2.CachedThreadPool
CachedThreadPool, which can be called a cacheable thread pool, is characterized by a continuous increase in the number of threads (theoretically up to integer.max_value)
Public static void testCachedThreadPool() {// Create a cacheable thread pool; ExecutorService ExecutorService = Executors.newCachedThreadPool(); for (int i = 0; i < 10; i++) { final int index = i; // sleep(1000); // sleep(1000); // sleep(1000); // } catch (InterruptedException e) { // e.printStackTrace(); //} executorService.execute(new Runnable() {public void run() {// Print out the threads executing Log.d(TAG, thread.currentThread ().getName()+ "being executed, "+ index+" times "); try { Thread.sleep(2000); } catch (InterruptedException e) { e.printStackTrace(); }}}); }}Copy the code
Output Log:
The 2021-08-07 15:21:20. 986, 27016-27095 / D/ThreadPoolUtil: Pool-1-thread-2 is being executed for the first time 2021-08-07 15:21:20.986 27016-27094/ D/ThreadPoolUtil: Pool-1-thread-1 is being executed, 0th time 2021-08-07 15:21:20.988 27016-27096/ D/ThreadPoolUtil: 2021-08-07 15:21:20.989 27016-27098/ D/ThreadPoolUtil: 2021-08-07 15:21:20.989 27016-27097/ D/ThreadPoolUtil: 2021-08-07 15:21:20.989 27016-27100/ D/ThreadPoolUtil: 2021-08-07 15:21:20.989 27016-27099/ D/ThreadPoolUtil: 2021-08-07 15:21:20.989 27016-27101/ D/ThreadPoolUtil: 2021-08-07 15:21:20.989 27016-27102/ D/ThreadPoolUtil: 989 27016-27103/ D/ThreadPoolUtil: pool-1-thread-10 is being executed for the 9th timeCopy the code
Analyze the Log information, again need to pay attention to the Log print time and the thread name. The maximum number of CachedThreadPool threads can be up to Integer.MAX_VALUE=2^31-1. So 10 tasks correspond to 10 threads, executing simultaneously.
Mind extension: Open the above comment code, that is, each time before the execution of a task to pause for 1s, so that there is a chance for the front thread to finish the task to be released, reuse.
The log information is as follows:
Set sleep for 1 second 2021-08-07 15:22:33.212 27277-27363/ D/ThreadPoolUtil: Pool-1-thread-1 is being executed for the 0th time 2021-08-07 15:22:34.218 27277-27368/ D/ThreadPoolUtil: Pool-1-thread-2 is being executed for the first time 2021-08-07 15:22:35.217 27277-27363/ D/ThreadPoolUtil: 2021-08-07 15:22:36.221 27277-27381/ D/ThreadPoolUtil: 2021-08-07 15:22:37.221 27277-27363/ D/ThreadPoolUtil: 2021-08-07 15:22:38.222 27277-27368/ D/ThreadPoolUtil: Pool-1-thread-2 is being executed for the 5th time 2021-08-07 15:22:39.222 27277-27381/ D/ThreadPoolUtil: 2021-08-07 15:22:40.223 27277-27363/ D/ThreadPoolUtil: 2021-08-07 15:22:41.223 27277-27368/ D/ThreadPoolUtil: 2021-08-07 15:22:42.224 27277-27381/ D/ThreadPoolUtil: pool-1-thread-3 is being executed for the 9th timeCopy the code
We can see that each thread executes tasks after 1s interval, and threads can be reused.
3.ScheduledThreadPool
ScheduledThreadPool, which supports scheduled or periodic task execution, has three methods to flexibly configure the frequency parameters;
Public static void testScheduledThreadPool() {// Create a fixed length thread pool, Support regular and periodic task execution - delay the ScheduledExecutorService ScheduledExecutorService = Executors. NewScheduledThreadPool (3); To perform a scheduledExecutorService. / / every x seconds scheduleAtFixedRate (new Runnable () {public void the run () { Log.d(TAG, thread.currentThread ().getName()+ "being executed "); } }, 1, 500, TimeUnit.MILLISECONDS); }Copy the code
Output Log:
The 2021-08-07 15:37:09. 965, 28901-28969 / D/ThreadPoolUtil: 2021-08-07 15:37:10.465 28901-28969/ D/ThreadPoolUtil: 2021-08-07 15:37:10.965 28901-28970/ D/ThreadPoolUtil: 2021-08-07 15:37:11.466 28901-28970/ D/ThreadPoolUtil: 2021-08-07 15:37:11.966 28901-28970/ D/ThreadPoolUtil: 2021-08-07 15:37:12.466 28901-28970/ D/ThreadPoolUtil: 2021-08-07 15:37:12.966 28901-29005/ D/ThreadPoolUtil: 2021-08-07 15:37:13.466 28901-29005/ D/ThreadPoolUtil: 2021-08-07 15:37:13.966 28901-29005/ D/ThreadPoolUtil: Pool 1-thread-3 is being executed 2021-08-07 15:37:14.466 28901-28969/ D/ThreadPoolUtil: pool 1-thread-1 is being executed.... Periodic print.....Copy the code
You can see that three threads execute tasks periodically. Because of the setting is the core number of threads is 3: Executors. NewScheduledThreadPool (3)
4.SingleThreadExecutor
SingleThreadExecutor, which uses a unique thread to execute tasks, for scenarios where all tasks need to be executed in the order they were submitted;
Public static void testSingleThreadExecutor() {// Create a single-threaded thread pool of ExecutorService singleThreadExecutor = Executors.newSingleThreadExecutor(); for (int i = 0; i < 10; i++) { final int index = i; SingleThreadExecutor. Execute (new Runnable () {public void the run () {try {/ / results in the output, Log.d(TAG, thread.currentThread ().getName()+ "being executed, "+ index+" time "); Thread.sleep(2000); } catch (InterruptedException e) { e.printStackTrace(); }}}); }}Copy the code
Output Log:
The 2021-08-07 15:25:02. 397, 27833-27896 / D/ThreadPoolUtil: Pool-1-thread-1 is being executed, 0th time 2021-08-07 15:25:04.398 27833-27896/ D/ThreadPoolUtil: Pool-1-thread-1 is being executed for the first time 2021-08-07 15:25:06.401 27833-27896/ D/ThreadPoolUtil: Pool-1-thread-1 is being executed for the second time 2021-08-07 15:25:08.404 27833-27896/ D/ThreadPoolUtil: Pool-1-thread-1 is being executed for the third time 2021-08-07 15:25:10.405 27833-27896/ D/ThreadPoolUtil: 2021-08-07 15:25:12.406 27833-27896/ D/ThreadPoolUtil: 2021-08-07 15:25:14.407 27833-27896/ D/ThreadPoolUtil: 2021-08-07 15:25:16.409 27833-27896/ D/ThreadPoolUtil: 2021-08-07 15:25:16.409 27833-27896/ D/ThreadPoolUtil: 2021-08-07 15:25:18.410 27833-27896/ D/ThreadPoolUtil: Is implemented - thread pool - 1-1, 8 times the 2021-08-07 15:25:20. 411, 27833-27896 / D/ThreadPoolUtil: - thread pool - 1-1 is implemented, 9 timesCopy the code
The log shows that a thread is executing tasks sequentially.
5.SingleThreadScheduledExecutor
SingleThreadScheduledExecutor, it have some similarities and SingleThreadExecutor, its core thread number is 1, but the maximum number of threads is an Integer. MAX_VALUE.
public static void testSingleThreadScheduledExecutor() { ScheduledExecutorService scheduledExecutorService = Executors.newSingleThreadScheduledExecutor(); for (int i = 0; i < 10; i++) { final int index = i; scheduledExecutorService.schedule(new Runnable() { @Override public void run() { try { Log.d(TAG, thread.currentThread ().getName()+ "being executed, "+ index+" times "); Thread.sleep(1); } catch (InterruptedException e) { e.printStackTrace(); } } }, 3L, TimeUnit.SECONDS); }}Copy the code
Log information is displayed:
The 2021-08-07 15:27:22. 167, 28291-28321 / D/ThreadPoolUtil: / D/ThreadPoolUtil: / D/ThreadPoolUtil: / D/ThreadPoolUtil: Pool-1-thread-1 is being executed for the first time 2021-08-07 15:27:22.172 28291-28321/ D/ThreadPoolUtil: Pool-1-thread-1 is being executed, 2nd time 2021-08-07 15:27:22.174 28291-28321/ D/ThreadPoolUtil: 2021-08-07 15:27:22.176 28291-28321/ D/ThreadPoolUtil: 2021-08-07 15:27:22.178 28291-28321/ D/ThreadPoolUtil: 2021-08-07 15:27:22.180 28291-28321/ D/ThreadPoolUtil: / D/ThreadPoolUtil: / D/ThreadPoolUtil: Pool-1-thread-1 is being executed for the seventh time 2021-08-07 15:27:22.185 28291-28321 / D/ThreadPoolUtil: pool-1-thread-1 is being executed for the 9th timeCopy the code
With 5. SingleThreadScheduledExecutor.
3. ThreadPoolExecutor method
There are five thread pools described above, and a look at the source code shows that all five common thread pools end up calling the ThreadPoolExecutor method.
public ThreadPoolExecutor(int corePoolSize,
int maximumPoolSize,
long keepAliveTime,
TimeUnit unit,
BlockingQueue<Runnable> workQueue) {
this(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue,
Executors.defaultThreadFactory(), defaultHandler);
}
Copy the code
The ThreadPoolExecutor method takes the following five arguments:
CorePoolSize: indicates the number of core threads in a thread pool
MaximunPoolSize: Indicates the maximum number of threads in the thread pool
KeeyAliveTime: Idle thread survival time
TimeUnit: indicates the survival TimeUnit
WorkQueue: a blocking queue that holds tasks waiting to be executed
Similarly, if we need to customize the thread pool, we can call the ThreadPoolExecutor method according to our business needs.
Iv. Rejection strategy
Four rejection policies are defined in the ThreadPoolExecutor class:
AbortPolicy discard task, and throws an exception RejectedExecutionException. Default policy.
DiscardPolicy Discard exceptions silently.
DiscardOldestPolicy attempts to compete for the first task, discarding the task at the top of the queue and resubmitting it for execution. DiscardOldestPolicy fails without throwing an exception.
CallerRunsPolicy uses the caller’s thread to execute – the thread that submitted the task, and goes back where it came from.
Finally, a thread pool flow chart is attached for further understanding: