从Java线程池及用法 一文中我们知道,Java提供了4个常用的线程池。但是在如下场景的的时候,就需要我们使用自定义ThreadPoolExecutor和BlockingQueue队列结合使用来处理。
//使用给定的初始参数和默认线程工厂以及拒绝的执行处理程序创建新的ThreadPoolExecutor。
//使用Executors工厂方法之一代替此通用构造函数可能更方便。
public ThreadPoolExecutor(int corePoolSize,
int maximumPoolSize,
long keepAliveTime,
TimeUnit unit,
BlockingQueue<Runnable> workQueue)
//使用给定的初始参数和默认拒绝执行处理程序创建新的ThreadPoolExecutor
public ThreadPoolExecutor(int corePoolSize,
int maximumPoolSize,
long keepAliveTime,
TimeUnit unit,
BlockingQueue<Runnable> workQueue,
ThreadFactory threadFactory)
//使用给定的初始参数和默认线程工厂创建一个新的code ThreadPoolExecutor
public ThreadPoolExecutor(int corePoolSize,
int maximumPoolSize,
long keepAliveTime,
TimeUnit unit,
BlockingQueue<Runnable> workQueue,
RejectedExecutionHandler handler)
//使用给定的初始参数创建一个新的ThreadPoolExecutor
public ThreadPoolExecutor(int corePoolSize,
int maximumPoolSize,
long keepAliveTime,
TimeUnit unit,
BlockingQueue<Runnable> workQueue,
ThreadFactory threadFactory,
RejectedExecutionHandler handler)
BlockingQueue是一个特殊的队列,当我们从BlockingQueue中取数据时,如果BlockingQueue是空的,
则取数据的操作会进入到阻塞状态,当 BlockingQueue 中有了新数据时,这个取数据的操作又会被重新唤醒。
同理,如果 BlockingQueue 中的数据已经满了,往 BlockingQueue 中存数据的操作又会进入阻塞状态,直到 BlockingQueue 中又有新的空间,存数据的操作又会被重新唤醒。它的泛型限定它是用来存放 Runnable 对象的。
public class Main {
public static void main(String[] args) {
BlockingQueue bq = new ArrayBlockingQueue(5);
ThreadPoolExecutor executor = new ThreadPoolExecutor(5, 30, 10, TimeUnit.SECONDS, bq);
executor.allowCoreThreadTimeOut(true);
for (int i = 0; i < 30; i++) {
executor.execute(new PrintDate());
}
}
public static class PrintDate implements Runnable {
@Override
public void run() {
String threadName = Thread.currentThread().getName();
System.out.println(threadName + ":" + System.currentTimeMillis());
}
}
}
corePoolSize=1
queueCapacity=Integer.MAX_VALUE
maxPoolSize=Integer.MAX_VALUE
keepAliveTime=60s
allowCoreThreadTimeout=false
rejectedExecutionHandler=AbortPolicy()
tasks :每秒的任务数,假设为500~1000
taskcost:每个任务花费时间,假设为0.1s
responsetime:系统允许容忍的最大响应时间,假设为1s
ThreadPoolExecutor 也向外提供了三个接口供我们自己扩展满足我们需求的线程池,这三个接口分别是:
public class MyThreadPool extends ThreadPoolExecutor {
private static final String TAG = "Bradley" ;
public MyThreadPool(int corePoolSize, int maximumPoolSize, long keepAliveTime, TimeUnit unit, BlockingQueue<Runnable> workQueue) {
super(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue);
}
@Override
protected void beforeExecute(Thread t, Runnable r) {
super.beforeExecute(t, r);
Log.d(TAG, "beforeExecute: 开始执行任务!");
}
@Override
protected void afterExecute(Runnable r, Throwable t) {
super.afterExecute(r, t);
Log.d(TAG, "beforeExecute: 任务执行结束!");
}
@Override
protected void terminated() {
super.terminated();
Log.d(TAG, "terminated: 线程池关闭!");
}
}
1.创建一个实现 Runnable 接口的类,并向外提供一个抽象方法供我们实现自定义功能,并实现 Comparable 接口,实现这个接口主要就是进行优先级的比较.
public abstract class PriorityRunnable implements Comparable<PriorityRunnable> ,Runnable{
private int priority;
public PriorityRunnable(int priority) {
if (priority < 0)
throw new IllegalArgumentException();
this.priority = priority;
}
@Override
public int compareTo(PriorityRunnable another) {
int my = this.getPriority();
int other = another.getPriority();
return my < other ? 1 : my > other ? -1 : 0;
}
@Override
public void run() {
doSth();
}
public abstract void doSth();
public int getPriority() {
return priority;
}
}
2.使用PriorityBlockingQueue队列
ThreadPoolExecutor executor = new ThreadPoolExecutor(3, 3, 0, TimeUnit.SECONDS, new PriorityBlockingQueue<Runnable>());
for (int i = 0; i < 30; i++) {
final int priority = i;
PriorityRunnable runnable = new PriorityRunnable(priority) {
@Override
public void doSth() {
String threadName = Thread.currentThread().getName();
Log.v(TAG, "线程:" + threadName + ",正在执行优先级为:" + priority + "的任务");
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
};
executor.execute(runnable);
}
}
Android 自定义线程池
ThreadPoolExecutor线程池参数设置技巧