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

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

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(),
            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 class UIUtils {

    /**
     * 获取上下文
     */
    public static Context getContext() {
        return MyApplication.getContext();
    }

    /**
     * 获取消息处理器
     */
    public static Handler getHandler() {
        return MyApplication.getHandler();
    }

    /**
     * 获取主线程
     */
    public static int getMainThread() {
        return MyApplication.getMainThreadId();
    }


    ///////判断是否运行在主线程//////////
    public static boolean isRunOnUiThread() {
        int myTid = android.os.Process.myTid();
        if (myTid == getMainThread())
            return true;
        return false;
    }

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

    public static void runOnUIThread(Runnable r,long s){
        getHandler().postDelayed(r,s);
    }

    public static String getCurrentProcessName(){
        int pid = android.os.Process.myPid();
        String processName="";
        ActivityManager manager=(ActivityManager)MyApplication.getContext().getSystemService(Context.ACTIVITY_SERVICE);
        for (ActivityManager.RunningAppProcessInfo process:manager.getRunningAppProcesses()){
            if(process.pid == pid){
                processName = process.processName;
            }
        }
        return processName;
    }


}

3:补充一个在自己定义的Application中提供所需的方法:

public class MyApplication extends MultiDexApplication {

    public static Activity activity;
    private static MyApplication application;
    private static Handler handler;
    private static int mainThreadId;
    private Context context;

    @Override
    public void onCreate() {
        super.onCreate();
        application = this;
        context = getApplicationContext();
        handler = new Handler();
        mainThreadId = android.os.Process.myPid();
    }
    
    /**
     * 获取到本应用的对象
     */
    public static MyApplication getApplication(){
        return application;
    }
    /**
     * 获取上下文
     */
    public static Context getContext(){
        return getApplication().getApplicationContext();
    }
    /**
     * 获取消息处理器
     */
    public static Handler getHandler(){
        return handler;
    }
    /**
     * 获取主线程id
     */
    public static int getMainThreadId(){
        return mainThreadId;
    }
    
    @Override
    protected void attachBaseContext(Context base) {
        super.attachBaseContext(base);
        MultiDex.install(this);
    }
    
}

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

public void initData() {
    APIConfig.getDataIntoView(new Runnable() {
        @Override
        public void run() {
           //这里做具体的任务在子线程中
           .........................

            UIUtils.runOnUIThread(new Runnable() {
                @Override
                public void run() {
                    //这里回到我们的主线程中来操作
            ...........................
                   
            });
        }
    });
}

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

你可能感兴趣的:(线程池)