开发中只要和网络打交道的基本上我们都会遇到多线程的问题,今天我们就来学习一下
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 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:经过这几步我们就完成了异步加载的整个流程,是不是很简单!