我们做项目的时候不可避免要接触到联网操作或者一些本地的耗时操作,而这些操作不是在主线程里面进行,会导致ANR异常(卡UI),所以我们要开辟子线程来执行这些操作,然而直接new Thread()会导致线程管理混乱而可能会到导致系统崩溃(如果一些循环操作不断开启线程一直new导致内存不足),所以我们有必要建立一个线程管理的工具类来管理这些线程,让我们的程序更健壮些,更好地去操作和使用线程。。。
直接进入主题-----
安卓里面有个线程池类ThreadPoolExecutor,这个类的常用构造方法为
ThreadPoolExecutor(int corePoolSize, int maximumPoolSize,
long keepAliveTime, TimeUnit unit,
RejectedExecutionHandler handler)
BlockingQueue<Runnable> workQueue,
RejectedExecutionHandler handler)
各个参数所对应的
corePoolSize: 线程池维护线程的最少数量
maximumPoolSize:线程池维护线程的最大数量
keepAliveTime: 线程池维护线程所允许的空闲时间
unit: 线程池维护线程所允许的空闲时间的单位
workQueue: 线程池所使用的缓冲队列
handler: 线程池对拒绝任务的处理策略
ThreadPoolExecutor 将根据 corePoolSize(最小线程数)和 maximumPoolSize(最大线程数)设置的边界自动调整池大小。当新任务在方法 execute(java.lang.Runnable) 中提交时,如果运行的线程少于 corePoolSize,则创建新线程来处理请求,即使其他辅助线程是空闲的。如果运行的线程多于corePoolSize 而少于 maximumPoolSize,则将请求放入队列等待,仅当队列满时才创建新线程,如果队列满已满但是线程数小于maximumPoolSize,则开启临时线程来执行任务,但是总的线程数不能超过maximumPoolSize,如果等于maximumPoolSize数量则要根据handler处理策略来进行操作线程。如果设置的 corePoolSize 和 maximumPoolSize相同,则创建了固定大小的线程池。如果将 maximumPoolSize 设置为基本的无界值(如 Integer.MAX_VALUE),则允许池适应任意数量的并发任务。在大多数情况下,核心和最大池大小仅基于构造来设置,不过也可以使用setCorePoolSize(int) 和 setMaximumPoolSize(int) 进行动态更改。
一.首先我们要手动创建一个线程池代理类,代码贴上-----
public class ThreadPoolProxy {
private ThreadPoolExecutor mExecutor;
private int corePoolSize;
private int maximumPoolSize;
private long keepAliveTime;
public ThreadPoolProxy(int corePoolSize, int maximumPoolSize, long keepAliveTime) {
this.corePoolSize = corePoolSize;
this.maximumPoolSize = maximumPoolSize;
this.keepAliveTime = keepAliveTime;
}
//双重锁机制
public ThreadPoolExecutor initThreadPoolExecutor() {
if (mExecutor == null) {
synchronized (ThreadPoolProxy.class) {
if (mExecutor == null) {
BlockingQueue<Runnable> workQueue = new LinkedBlockingDeque<Runnable>();
ThreadFactory threadFactory = Executors.defaultThreadFactory();
RejectedExecutionHandler handler = new ThreadPoolExecutor.AbortPolicy();
mExecutor = new ThreadPoolExecutor(corePoolSize,
maximumPoolSize,
keepAliveTime,
TimeUnit.SECONDS,
workQueue,
threadFactory,
handler);
}
}
}
return mExecutor;
}}
然后在设置一些执行或移除等对线程操作的方法供调用
//试行任务
public void execute(Runnable task) {
initThreadPoolExecutor();
mExecutor.execute(task);
}
//移除任务
public void remove(Runnable task) {
initThreadPoolExecutor();
mExecutor.remove(task);
}
//提交任务(Future+execute(Runnable task)
public Future<?> submit(Runnable task) {
initThreadPoolExecutor();
return mExecutor.submit(task);
}
二. 建立一个线程池工厂类ThreadPoolFactory,顾名思义,工厂类就可以生产出用户定制所想要的线程池出来,贴代码
public class ThreadPoolFactory {
private static ThreadPoolProxy commonThreadPool;
public static final int Common_CORE_POOL_SIZE = 5;
public static final int Common_MAX_POOL_SIZE = 5;
public static final int Common_KEEP_LIVE_TIME = 1; //存活时间
//单例模式
public static ThreadPoolProxy getCommonThreadPool() {
if (commonThreadPool == null) {
synchronized (ThreadPoolFactory.class) {
if (commonThreadPool == null) {
commonThreadPool = new ThreadPoolProxy(Common_CORE_POOL_SIZE, Common_MAX_POOL_SIZE, Common_KEEP_LIVE_TIME);
}
}
}
return commonThreadPool; //返回所要的线程池
}
}
三.建立一个线程池工具类(操作类)来对我们所产生的线程池进行操作
public class ThreadPoolUtils {
//在非UI线程中执行
public static void runTaskInThread(Runnable task){
ThreadPoolFactory.getCommonThreadPool().execute(task);
}
//在UI线程中执行
private static Handler handler = new Handler();
public static void runTaskInUIThread(Runnable task){
handler.post(task);
}
}
在主线程操作我们用handler来分发处理任务。。
对了,我们还可以自定义Toast
//在UI线程
public static void showToastInUIThread(String content){
Toast.makeText(BaseApplication.getContext(), content, Toast.LENGTH_SHORT).show();
}
//在工作线程
public static void showToastInThread(final String content){
ThreadPoolUtils.runTaskInThread(new Runnable() {
@Override
public void run() {
Toast.makeText(BaseApplication.getContext(), content, Toast.LENGTH_SHORT).show();
}
});
}
这样我们就可以方便的弹出吐司
。。。
。。
。