Android中线程池的使用之单例设计模式

Published on in JAVA with 0 views and 0 comments

开发中只要和网络打交道的基本上我们都会遇到多线程的问题,今天我们就来学习一下

Android中线程池的使用,很多时候我们使用多线程都是new一个Thread来进行子线程的

任务处理:但是这其中牵涉到几个问题:

    (1):线程的创建,销毁等需要巨大的开销

    (2):线程的安全性问题,这个当我们接触稍微大点的项目的时候就会出现

    (3):多个线程不容易管理,比较麻烦等。

1:下面直接上代码:创建一个类专门用来管理线程:

**
 * 本应用的线程管理器,1:首先要做一个池子 2:必须做成单例模式(懒汉),防止创建多个线程,达不到管理效果
 * 3:考虑线程安全问题
 * Created by acer-pc on 2018/6/19.
 */
 
public class ThreadManager {
 
 private static ThreadPool mThreadPool;
 
public static ThreadPool getThreadPool() {
   if (mThreadPool == null) {
      synchronized (ThreadManager.class) {
         if (mThreadPool == null) {
            
            int cpuCount = Runtime.getRuntime().availableProcessors(); // 获取cpu数量,即核数
            int threadCount = cpuCount*2+1; //线程池中线程的个数---cpu核数*2+1--性能最佳
 
            mThreadPool = new ThreadPool(threadCount,threadCount,1L);
         }
      }
   }
   return mThreadPool;
 
}
 
// 线程池---对系统的线程池做的封装
public static class ThreadPool {
   private int corePoolSize;
   private int maximumPoolSize;
   private long keepAliveTime;
  
   private ThreadPoolExecutor executor; // 执行体-->系统底层自带的线程池
   private Runnable r;
 
   
   public ThreadPool(int corePoolSize, int maximumPoolSize,
         long keepAliveTime) {
      super();
      this.corePoolSize = corePoolSize;
      this.maximumPoolSize = maximumPoolSize;
      this.keepAliveTime = keepAliveTime;
   }
   
   
   
   //1.执行任务
   public void exeute(Runnable r) {
      
      if(executor == null){
      executor = new ThreadPoolExecutor(corePoolSize,
            maximumPoolSize, keepAliveTime, TimeUnit.SECONDS,
            new LinkedBlockingDeque<Runnable>(),
            Executors.defaultThreadFactory(),
            new AbortPolicy());
      // 参数1:corePoolSize核心线程数;参数2:maximumPoolSize最大线程数;参数3:keepAliveTime休息时间;参数4:unit时间单位;参数5:workQueue线程队列;参数6:threadFactory线程工厂;参数7:handler异常处理策略
      }
 
      
      //线程池执行一个runnable对象,具体运行时机线程池executor底层说了算
      executor.execute(r);
      
   }
   
   //2.取消任务
   public void cancel(Runnable r){
      if(executor != null){
         //从线程未开始的排队队列中移除对象
         executor.getQueue().remove(r);
         
      }
   }
}
}

2:再单独创建一个全局的类(我们就叫APIConfig类吧),用来调用线程池,类中使用如下方法调用:

public static void getDataIntoView(Runnable runnable) {
    ThreadManager.getThreadPool().exeute(runnable);
}

3: 单独再创建一个工具类(我们就叫UIUtils 类吧)来从方便从子线程切换到主线程中去,类中方法如下:

public static void runOnUIThread(Runnable r){
    if(isRunOnUiThread()){
        r.run();
    }else{
        getHandler().post(r);//如果是子线程,借助handler让其运行在主线程
    }
}

3:使用的时候(在我们需要使用的类中假如初始化数据是用initData()方法)就直接按如下方法调用就可以了:

public void initData() {
    APIConfig.getDataIntoView(new Runnable() {
        @Override
        public void run() {
           //这里做具体的任务在子线程中
           .........................
 
            UIUtils.runOnUIThread(new Runnable() {
                @Override
                public void run() {
                    //这里回到我们的主线程中来操作
            ...........................
                   
            });
        }
    });
}

4:经过这几步我们就完成了异步加载的整个流程,是不是很简单!

说你懂得生之微末,我便做了这壮大与你看,你说再热闹也终需离散,我便做了这一辈子与你看,你说冷暖自知,我便做了这冬花夏雪与你看,你说恋恋旧日好时光,我便做了这描金绣凤的浮世绘与你看。你说应愁高处不胜寒,我便拱手河山,讨你欢。