Detailed explanation of java/android thread pool
First, a brief description of thread pools:
How does a thread pool work: After a series of tasks appear, tasks are arranged according to their own thread pool.
As shown in the picture:
The benefits of thread pooling:
1. Reuse threads in the thread pool to avoid performance overhead due to thread creation and destruction.
2. It can effectively control the maximum concurrency number of thread pools and avoid the blocking phenomenon caused by the preemption of system resources among a large number of threads.
3. It can manage threads simply. It also provides functions such as timing execution and specified interval loop execution.
The specific implementation of thread pool is ThreadPool Exeutor, whose interface is Executor.
ThreadPool Executor provides a series of parameters for configuring thread pools.
public ThreadPoolExecutor(int corePoolSize,
int maximumPoolSize,
long keepAliveTime,
TimeUnit unit,
BlockingQueue<Runnable> workQueue,
ThreadFactory threadFactory) {
this(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue,
threadFactory, defaultHandler);
}
The parameters are as follows:
corePoolSize: Number of core threads in the thread pool. By default, core threads will survive in the thread pool even if they are idle. It has an allowCoreThreadTimeOut property. If set to true, the core thread pool will have a timeout policy. The time-out is the third parameter, keepAliveTime. If the timeout occurs, the core thread is terminated.
2, maxmum PoolSize: The maximum number of threads that a thread pool can tolerate. When the number of active threads reaches this value, subsequent new tasks will be blocked.
3, keep AliveTime: The time-out when a non-core thread is idle is longer than that, and the non-core thread will be recycled. This parameter, like the first parameter, also acts on the core thread if the relevant properties are set.
4, unit: Specifies the parameter time unit of keepAliveTime. This is an enumeration, commonly used are MILLISECONDS (milliseconds), SECONDS (seconds), etc.
5, workQueue: Task queue of thread pool. The unable object submitted by execute() method (execution method) is stored in this parameter.
6, threadFactory: Thread Factory, which provides the function of creating new threads for thread pools.
In carrying out their tasks, they generally follow the following rules:
1. If the thread reaches the number of core threads, a core thread will be started directly.
2. Threads do not reach the number of core threads, and tasks are inserted into the workQueue queue.
3. If the task queue is full and step 2 cannot be inserted into the task queue, a non-core thread execution is started.
4. If the number of threads in Step 3 reaches the maxmum Pool Size, the task is refused.
Secondly, the analysis of the related class structure of thread pool
Take a look at the class structure diagram of the thread pool:
Say the following points:
This is an abstract factory model! The difference between Executor and Executors:
Executor is just an interface, it has only one method, execute() method (execution method).
public interface Executor {
void execute(Runnable command);
}
Executors is a method that does not inherit any classes. It acts as a factory method class for creating various objects such as thread pools. For example: Fixed ThreadPool, default ThreadFactory (more specifically below), and these specific thread pool schemes (Fixed ThreadPool) or custom thread pool schemes (ThreadPool Exeutor) are from the Executor Service interface, which is also inherited from the Executor interface. You can see it clearly through the class structure diagram.
For example, Executors produces ExecutorService objects with the following source code
public static ExecutorService newSingleThreadExecutor(ThreadFactory threadFactory) {
return new FinalizableDelegatedExecutorService
(new ThreadPoolExecutor(1, 1,
0L, TimeUnit.MILLISECONDS,
new LinkedBlockingQueue<Runnable>(),
threadFactory));
}
Speaking of factory mode, ThreadPoolExeutor's parameter threadFactory is an interface with only the newThread method. The code is as follows
public interface ThreadFactory {
Thread newThread(Runnable r);
}
Its function is similar to executor interface, which embodies the idea of Interface-oriented programming. For example, the following two methods are ThreadFactory objects generated by the factory method class Executors.
public static ThreadFactory defaultThreadFactory() {
return new DefaultThreadFactory();
}
public static ThreadFactory privilegedThreadFactory() {
return new PrivilegedThreadFactory();
}
defaultThreadFactory creates threads in this way, so if you want to customize it, you may refer to it.
static class DefaultThreadFactory implements ThreadFactory {
private static final AtomicInteger poolNumber = new AtomicInteger(1);
private final ThreadGroup group;
private final AtomicInteger threadNumber = new AtomicInteger(1);
private final String namePrefix;
DefaultThreadFactory() {
SecurityManager s = System.getSecurityManager();
group = (s != null) ? s.getThreadGroup() :
Thread.currentThread().getThreadGroup();
namePrefix = "pool-" +
poolNumber.getAndIncrement() +
"-thread-";
}
public Thread newThread(Runnable r) {
Thread t = new Thread(group, r,
namePrefix + threadNumber.getAndIncrement(),
0);
if (t.isDaemon())
t.setDaemon(false);
if (t.getPriority() != Thread.NORM_PRIORITY)
t.setPriority(Thread.NORM_PRIORITY);
return t;
}
}
The Use of Three Specific Thread Pools
Having said so much, we need to look specifically at the thread pool provided by the system, mainly these four:
FixedTreadPool. fixed has a solid meaning, created by the new FixedThreadPool method of the factory method class Executors. It is a thread pool with a fixed number of threads, only core threads and no timeout policy, so threads will not be recycled. This means that it can respond quickly to external requests.
Example: Four runnable s and two core threads are set up here.
Runnable runnable = new Runnable() {
@Override
public void run() {
Log.d("hello","sleep Front");
SystemClock.sleep(3000);
Log.d("hello", "sleep after");
}
};
......
ExecutorService executorService = Executors.newFixedThreadPool(2);
executorService.execute(runnable);
executorService.execute(runable1);
executorService.execute(runable2);
executorService.execute(runable3);
The output is as follows.
06-24 15:49:47.962 12462-12497/? D/hello: sleep1 Front
06-24 15:49:47.962 12462-12496/? D/hello: sleepFront
06-24 15:49:50.962 12462-12497/com.example.hang.myapplication D/hello: sleep1 after
06-24 15:49:50.962 12462-12497/com.example.hang.myapplication D/hello: sleep2 Front
06-24 15:49:50.972 12462-12496/com.example.hang.myapplication D/hello: sleepafter
06-24 15:49:50.972 12462-12496/com.example.hang.myapplication D/hello: sleep3 Front
06-24 15:49:53.962 12462-12497/com.example.hang.myapplication D/hello: sleep2 after
06-24 15:49:53.972 12462-12496/com.example.hang.myapplication D/hello: sleep3 after
As you can see, there are only two threads to execute at a time, and when one of them finishes, it's the next one.
When the number of core threads is changed to 4, the four runnable s are executed at one time.
1. CachedThreadPool. It is a thread pool with an indefinite number of threads. Only non-core threads can be understood simply as the maximum number of threads is infinite. CachedThreadPool's task queue is equivalent to an empty set, which causes any task to be executed immediately and is more suitable for doing a lot of tasks with less time.
For example, modify the above Executor Service executor Service = Executors. new Fixed ThreadPool (2); replace it with
ExecutorService executorService = Executors.newCachedThreadPool(); the output is as follows, four threads are executed at one time, and the sequence of threads is uncertain.
06-24 15:53:08.582 16801-16873/com.example.hang.myapplication D/hello: sleep2 Front
06-24 15:53:08.582 16801-16872/com.example.hang.myapplication D/hello: sleep1 Front
06-24 15:53:08.582 16801-16871/com.example.hang.myapplication D/hello: sleepFront
06-24 15:53:08.582 16801-16875/com.example.hang.myapplication D/hello: sleep3 Front
06-24 15:53:11.582 16801-16873/com.example.hang.myapplication D/hello: sleep2 after
06-24 15:53:11.582 16801-16872/com.example.hang.myapplication D/hello: sleep1 after
06-24 15:53:11.582 16801-16871/com.example.hang.myapplication D/hello: sleepafter
06-24 15:53:11.582 16801-16875/com.example.hang.myapplication D/hello: sleep3 after
1. Scheduled ThreadPool. Scheduled means "scheduled". The number of core thread pools is fixed and non-core thread pools are unrestricted. Non-core thread pools will be reclaimed immediately when they are idle. It is mainly used to perform timed tasks and repetitive tasks with fixed cycle.
Example: Here is a delay of 2000 ms to start execution
ScheduledExecutorService scheduledExecutorService = Executors.newScheduledThreadPool(3);
scheduledExecutorService.schedule(runnable,2000, TimeUnit.MILLISECONDS);
scheduledExecutorService.schedule(runable1, 2000, TimeUnit.MILLISECONDS);
scheduledExecutorService.schedule(runable2, 2000, TimeUnit.MILLISECONDS);
scheduledExecutorService.schedule(runable3, 2000, TimeUnit.MILLISECONDS);
Example: runnable is executed every 1000ms after a delay of 10 ms.
scheduledExecutorService.scheduleAtFixedRate(runnable,10,1000,TimeUnit.MILLISECONDS);
1. SingleThreadExecutor. has only one core thread, so make sure that all tasks are executed sequentially in one thread. Put all tasks in one thread, which has the advantage of not having to deal with thread synchronization.
Let's not do an example here, that is, four queues are executed sequentially without disorder.
06-24 16:05:02.782 32057-32125/com.example.hang.myapplication D/hello: sleepFront
06-24 16:05:05.782 32057-32125/com.example.hang.myapplication D/hello: sleepafter
06-24 16:05:05.782 32057-32125/com.example.hang.myapplication D/hello: sleep1 Front
06-24 16:05:08.782 32057-32125/com.example.hang.myapplication D/hello: sleep1 after
06-24 16:05:08.782 32057-32125/com.example.hang.myapplication D/hello: sleep2 Front
06-24 16:05:11.782 32057-32125/com.example.hang.myapplication D/hello: sleep2 after
06-24 16:05:11.782 32057-32125/com.example.hang.myapplication D/hello: sleep3 Front
06-24 16:05:14.782 32057-32125/com.example.hang.myapplication D/hello: sleep3 after