如何在 Android 中使用 ThreadPoolExecutor?
任务队列包含等待由池的任何空闲线程执行的作业。生产者有助于任务队列中,而工作线程作为消费者函数,消耗来自队列作业每当空闲线程是准备进行新的后台操作。
但在我们深入研究之前,Android 中的线程池到底是什么?
它是一个线程池程序,它处理与线程相关的所有任务并涉及它们,尽管适当的线程数与线程池程序的实现方式成正比。
线程池执行器
ThreadPoolExecutor使用其线程池中的一个线程来完成特定作业。
Java
ThreadPoolExecutor gfgPoolExecutor
= new ThreadPoolExecutor(
int mainPoolSize,
long keepAliveTime,
int maximumPoolSize,
TimeUnit unit,
BlockingQueue workQueue
);
Java
public class GfGThreadMechanism implements ThreadFactory {
private final int gfgPriority;
public PriorityThreadFactory(int threadPriority) {
gfgPriority = threadPriority;
}
@Override
public Thread newThread(final Runnable gfgRunner) {
Runnable wrapperRunnable = new Runnable() {
@Override
public void run() {
try {
Process.setThreadPriority(gfgPriority);
} catch (Throwable t) {
}
gfgRunner.run();
}
};
return new Thread(wrapperRunnable);
}
}
Java
public class MasterThreadExecutor implements Executor {
private final Handler gfgHandler = new Handler(Looper.getMainLooper());
@Override
public void execute(Runnable runnable) {
gfgHandler.post(runnable);
}
}
Java
public class gfgExecutor{
// Number of threads, are being set here.
public static final int NUMBER_OF_THREADS = Runtime.getRuntime().availableProcessors();
// Setting and Monitoring BG Tasks
private final ThreadPoolExecutor gfgTasks;
// another executor for handling light feather tasks
private final ThreadPoolExecutor gfgFeatherTasks;
// the thread pool which manages the heavy tasks
private final Executor publicExecutor;
// an instance of DefaultExecutorSupplier
private static DefaultExecutorSupplier gfgInstance;
// returns the instance of DefaultExecutorSupplier
public static DefaultExecutorSupplier getInstance() {
if (gfgInstance == null) {
synchronized(DefaultExecutorSupplier.class){
gfgInstance = new DefaultExecutorSupplier();
}
return gfgInstance;
}
// Main Magic Goes Here
private DefaultExecutorSupplier() {
// setting the thread factory
ThreadFactory backgroundPriorityThreadFactory = new
PriorityThreadFactory(Process.THREAD_PRIORITY_BACKGROUND);
// setting the thread pool executor for gfgTasks;
gfgTasks = new ThreadPoolExecutor(
NUMBER_OF_THREADS * 2,
NUMBER_OF_THREADS * 2,
60L,
TimeUnit.SECONDS,
new LinkedBlockingQueue(),
backgroundPriorityThreadFactory
);
// setting the thread pool executor for gfgFeatherTasks;
gfgFeatherTasks = new ThreadPoolExecutor(
NUMBER_OF_THREADS * 2,
NUMBER_OF_THREADS * 2,
60L,
TimeUnit.SECONDS,
new LinkedBlockingQueue(),
backgroundPriorityThreadFactory
);
// setting the thread pool executor for gfgExecutor;
gfgExecutor = new MainThreadExecutor();
}
// thread pool which returns the BG task
public ThreadPoolExecutor forBackgroundTasks() {
return gfgTasks;
}
// similar to the return above, but for feather tasks
public ThreadPoolExecutor forLightWeightBackgroundTasks() {
return gfgFeatherTasks;
}
// similar to the return above, but for heavy tasks
public Executor forMainThreadTasks() {
return mMainThreadExecutor;
}
}
Java
// The different urgency levels
public enum Urgency {
// Lowest urgency level
LOW,
// Medium urgency level
MEDIUM,
// Highest urgency level
HIGH,
// Highest urgency level,
// even up from the previous
IMMEDIATE;
}
Java
public class UrgencyRunnable implements Runnable {
private final Priority gfgUrgency;
public PriorityRunnable(Priority gfgUrgency) {
this.gfgUrgency = gfgUrgency;
}
@Override
public void run() {
// your code, or leave blank.
}
public Priority gfgUrgency() {
return gfgUrgency;
}
}
Java
public class UrgencyExecutor extends ThreadPoolExecutor {
public PriorityThreadPoolExecutor(int gfgPool, int gfgMax, long gfgTime,
TimeUnit unit, ThreadFactory threadFactory) {
super(gfgPool, gfgMax, gfgTime, unit,new PriorityBlockingQueue(), threadFactory);
}
@Override
public gfgTask> submit(Runnable gfgBackTask) {
PriorityFutureTask gfgTask = new PriorityFutureTask((PriorityRunnable) task);
execute(gfgTask);
return gfgTask;
}
private static final class PriorityFutureTask extends FutureTask
implements Comparable {
private final PriorityRunnable priorityRunnable;
public gfgTask(PriorityRunnable priorityRunnable) {
super(priorityRunnable, null);
this.priorityRunnable = priorityRunnable;
}
@Override
public int compareTo(gfgTask other) {
Priority gfg1 = priorityRunnable.getPriority();
Priority gfg2 = other.priorityRunnable.getPriority();
return gfg2.ordinal() - gfg1.ordinal();
}
}
}
Java
public class DefaultExecutorSupplier{
private final PriorityThreadPoolExecutor gfgBackTask;
private DefaultExecutorSupplier() {
gfgBackTask = new PriorityThreadPoolExecutor(
NUMBER_OF_THREADS * 4,
NUMBER_OF_THREADS * 3,
50L,
TimeUnit.SECONDS,
backgroundPriorityThreadFactory
);
}
}
Java
// Doing at LOW
public void doingAtLowUrgency(){
DefaultExecutorSupplier.getInstance().forBackgroundTasks()
.submit(new PriorityRunnable(Priority.LOW) {
@Override
public void run() {
// some back tasks go here
}
});
}
您可能想知道所有这些值指的是什么?
- mainPoolSize :池中始终保持的线程数。一开始池中没有线程。但是,将作业添加到队列时会生成新线程。如果有空闲线程但线程数小于mainPoolSize,则会继续生成新线程。
- keepAliveTime:当线程数超过核心线程数时,非核心线程(多余的空闲线程)将等待新的作业,如果在该参数指示的时间段内没有得到一个则终止。
- maximumPoolSize:池中可以同时存在的最大线程数。如果这超过了 mainPoolSize,并且当前线程数大于 mainPoolSize,则只有在队列为空时才会生成额外的工作线程。
- unit: keepAliveTime 的时间单位。
- workQueue:任务队列,只保存可以执行的作业。它必须是一个 BlockingQueue。
问题来了,
为什么要在 Android 或Java应用程序中使用线程池执行器?
它是一个强大的任务执行框架,因为它允许任务队列插入、任务取消和任务优先级排序。它通过管理其线程池中预定数量的线程来降低与线程创建相关的开销。
Geek Tip: The number of threads available for different thread pools may vary depending on your needs.
如何在 Android 中使用线程池
第 1 步:创建 GfGThreadMechanism
Java
public class GfGThreadMechanism implements ThreadFactory {
private final int gfgPriority;
public PriorityThreadFactory(int threadPriority) {
gfgPriority = threadPriority;
}
@Override
public Thread newThread(final Runnable gfgRunner) {
Runnable wrapperRunnable = new Runnable() {
@Override
public void run() {
try {
Process.setThreadPriority(gfgPriority);
} catch (Throwable t) {
}
gfgRunner.run();
}
};
return new Thread(wrapperRunnable);
}
}
第 2 步:创建主线程执行器
Java
public class MasterThreadExecutor implements Executor {
private final Handler gfgHandler = new Handler(Looper.getMainLooper());
@Override
public void execute(Runnable runnable) {
gfgHandler.post(runnable);
}
}
第 3 步:创建一个单例类来执行
Java
public class gfgExecutor{
// Number of threads, are being set here.
public static final int NUMBER_OF_THREADS = Runtime.getRuntime().availableProcessors();
// Setting and Monitoring BG Tasks
private final ThreadPoolExecutor gfgTasks;
// another executor for handling light feather tasks
private final ThreadPoolExecutor gfgFeatherTasks;
// the thread pool which manages the heavy tasks
private final Executor publicExecutor;
// an instance of DefaultExecutorSupplier
private static DefaultExecutorSupplier gfgInstance;
// returns the instance of DefaultExecutorSupplier
public static DefaultExecutorSupplier getInstance() {
if (gfgInstance == null) {
synchronized(DefaultExecutorSupplier.class){
gfgInstance = new DefaultExecutorSupplier();
}
return gfgInstance;
}
// Main Magic Goes Here
private DefaultExecutorSupplier() {
// setting the thread factory
ThreadFactory backgroundPriorityThreadFactory = new
PriorityThreadFactory(Process.THREAD_PRIORITY_BACKGROUND);
// setting the thread pool executor for gfgTasks;
gfgTasks = new ThreadPoolExecutor(
NUMBER_OF_THREADS * 2,
NUMBER_OF_THREADS * 2,
60L,
TimeUnit.SECONDS,
new LinkedBlockingQueue(),
backgroundPriorityThreadFactory
);
// setting the thread pool executor for gfgFeatherTasks;
gfgFeatherTasks = new ThreadPoolExecutor(
NUMBER_OF_THREADS * 2,
NUMBER_OF_THREADS * 2,
60L,
TimeUnit.SECONDS,
new LinkedBlockingQueue(),
backgroundPriorityThreadFactory
);
// setting the thread pool executor for gfgExecutor;
gfgExecutor = new MainThreadExecutor();
}
// thread pool which returns the BG task
public ThreadPoolExecutor forBackgroundTasks() {
return gfgTasks;
}
// similar to the return above, but for feather tasks
public ThreadPoolExecutor forLightWeightBackgroundTasks() {
return gfgFeatherTasks;
}
// similar to the return above, but for heavy tasks
public Executor forMainThreadTasks() {
return mMainThreadExecutor;
}
}
现在在任何活动中使用这个类,你准备好了!
您如何确定任务的优先级?
假设队列中有 10 个作业,线程池只能处理 4 个线程。因为线程池一次只能执行四个活动,所以我们优先考虑新的工作。但是假设我们需要先完成放入队列中的最后一个作业。我们需要赋予该作业 IMMEDIATE 优先级,以便当线程从队列中获取新任务时,它首先运行它(因为它具有最高优先级)。要优先处理一个作业,我们必须首先构建一个线程池执行器。
创建优先 ENUM:
Java
// The different urgency levels
public enum Urgency {
// Lowest urgency level
LOW,
// Medium urgency level
MEDIUM,
// Highest urgency level
HIGH,
// Highest urgency level,
// even up from the previous
IMMEDIATE;
}
然后,我们为紧急情况创建一个可运行的:
Java
public class UrgencyRunnable implements Runnable {
private final Priority gfgUrgency;
public PriorityRunnable(Priority gfgUrgency) {
this.gfgUrgency = gfgUrgency;
}
@Override
public void run() {
// your code, or leave blank.
}
public Priority gfgUrgency() {
return gfgUrgency;
}
}
通过扩展 ThreadPoolExecutor 来创建 PriorityThreadPoolExecutor 。
必须创建 PriorityFutureTask,它将实现
Java
public class UrgencyExecutor extends ThreadPoolExecutor {
public PriorityThreadPoolExecutor(int gfgPool, int gfgMax, long gfgTime,
TimeUnit unit, ThreadFactory threadFactory) {
super(gfgPool, gfgMax, gfgTime, unit,new PriorityBlockingQueue(), threadFactory);
}
@Override
public gfgTask> submit(Runnable gfgBackTask) {
PriorityFutureTask gfgTask = new PriorityFutureTask((PriorityRunnable) task);
execute(gfgTask);
return gfgTask;
}
private static final class PriorityFutureTask extends FutureTask
implements Comparable {
private final PriorityRunnable priorityRunnable;
public gfgTask(PriorityRunnable priorityRunnable) {
super(priorityRunnable, null);
this.priorityRunnable = priorityRunnable;
}
@Override
public int compareTo(gfgTask other) {
Priority gfg1 = priorityRunnable.getPriority();
Priority gfg2 = other.priorityRunnable.getPriority();
return gfg2.ordinal() - gfg1.ordinal();
}
}
}
首先,使用 PriorityThreadPoolExecutor代替 DefaultExecutorSupplier 中的 ThreadPoolExecutor,如下所示:
Java
public class DefaultExecutorSupplier{
private final PriorityThreadPoolExecutor gfgBackTask;
private DefaultExecutorSupplier() {
gfgBackTask = new PriorityThreadPoolExecutor(
NUMBER_OF_THREADS * 4,
NUMBER_OF_THREADS * 3,
50L,
TimeUnit.SECONDS,
backgroundPriorityThreadFactory
);
}
}
以下是我们如何将工作设为低优先级的示例:
Java
// Doing at LOW
public void doingAtLowUrgency(){
DefaultExecutorSupplier.getInstance().forBackgroundTasks()
.submit(new PriorityRunnable(Priority.LOW) {
@Override
public void run() {
// some back tasks go here
}
});
}
结论
可以以这种方式对任务进行优先级排序。上述实现也适用于任何Java应用程序。希望这篇文章为你清除空气!