Android优化笔记--多线程优化

        在Android项目中,我们创建的Service、Activity以及Broadcast均是一个主线程处理,这里我们可以理解为UI线程.但是在操作一些耗时操作时,比如I/O读写的大文件读写,数据库操作以及网络下载需要很长时间,为了不阻塞用户界面,出现ANR的响应提示窗口,这个时候我们可以考虑使用Thread线程来解决.先来简单了解一下线程的调度原理及模型:

线程调度原理:
任一时刻,只有一个线程占用CPU,处于运行状态
多线程并发:
轮流获取CPU使用权

线程调度模型:
分时调度模型:轮流获取、均分CPU时间
抢占式调度模型:优先级好的获取,JVM采用这种方式。
nice值、cgroup

nice值:
1)Process中定义
2)值越小,优先级越高
3)默认是THREAD_PRIORITY_DEFAULT,0

cgroup:
1) 更严格的群组调度策略。
2) 保证前台线程可以获取到更多的CPU
注意点:
线程过多会导致CPU频繁切换,降低线程运行效率
正确认识任务重要性决定哪种优先级。 (工作量越大优先级越低)
优先级具有继承性

常见使用方式:

不正确使用方式:
new  Thread(new  Runnable()  {
  @Override
  public  void  run()  {
    //执行业务
  }
}).start();

缺点:
a. 每次new Thread新建对象,性能相对较差;
b. 线程缺乏统一管理,可能无限制新建线程,相互之间竞争,及可能占用过多系统资源导致anr死机或oom;

相比new Thread,Java提供的四种线程池的好处在于: 
1. 重用存在的线程,减少对象创建、消亡的开销,性能佳。 
2. 可有效控制最大并发线程数,提高系统资源的使用率,同时避免过多资源竞争,避免堵塞。 
3. 提供定时执行、定期执行、单线程、并发数控制等功能。

四种线程池的创建方式:
newCacheThreadPool一个无限大并可以缓存的线程池。在之前创建新线程的时刻首先复用已经创建过的空闲线程。
ExecutorService cacheThreadPool = Executors.newCachedThreadPool();


newFixedThreadPool 可以控制最大并发数的线程池。超过最大并发数的线程进入等待队列
ExecutorService fixedThreadPool = Executors.newFixedThreadPool(3);

newScheduledThreadPool 一个可以定时执行的线程池。

ScheduledExecutorService scheduledThreadPool = Executors.newScheduledThreadPool(5);
        scheduledThreadPool.schedule(new Runnable() {
            @Override
            public void run() {
               
            }
        },1, TimeUnit.SECONDS);


newSingleThreadExecutor 单线程化线程池。支持FIFO、LIFO的优先级执行。
ExecutorService singleThreadExecutor = Executors.newSingleThreadExecutor();

以上都是在说创建线程池并且将业务代码放到线程池中,如果应用中很多地方都需要多线程,如果我们都去new 线程池的话,就会造成线程池代码冗余,代码阅读性较差,这时我们需要一个线程池管理工具,如下:

public class AppExecutors {
    private static final String TAG = "AppExecutors";
    /**磁盘IO线程池**/
    private final ExecutorService diskIO;
	/**网络IO线程池**/
    private final ExecutorService networkIO;
	/**UI线程**/
    private final Executor mainThread;
	/**定时任务线程池**/
    private final ScheduledExecutorService scheduledExecutor;

    public static AppExecutors getInstance() {
        if (appExecutors == null) {
            synchronized (AppExecutors.class) {
                if (appExecutors == null) {
                    appExecutors = new AppExecutors();
                }
            }
        }
        return appExecutors;
    }


    public AppExecutors(ExecutorService diskIO, ExecutorService networkIO, Executor mainThread, ScheduledExecutorService scheduledExecutor) {
        this.diskIO = diskIO;
        this.networkIO = networkIO;
        this.mainThread = mainThread;
        this.scheduledExecutor = scheduledExecutor;
    }

    public AppExecutors() {
        this(diskIoExecutor(), networkExecutor(), new MainThreadExecutor(), scheduledThreadPoolExecutor());
    }
	/**
	 * 定时(延时)任务线程池
	 * 
	 * 替代Timer,执行定时任务,延时任务
	 */
    public ScheduledExecutorService scheduledExecutor() {
        return scheduledExecutor;
    }

	/**
	 * 磁盘IO线程池(单线程)
	 * 
	 * 和磁盘操作有关的进行使用此线程(如读写数据库,读写文件)
	 * 禁止延迟,避免等待
	 * 此线程不用考虑同步问题 
 	 */
    public ExecutorService diskIO() {
        return diskIO;
    }
	/**
	 * 网络IO线程池
	 * 
	 * 网络请求,异步任务等适用此线程
	 * 不建议在这个线程 sleep 或者 wait  
	 */
    public ExecutorService networkIO() {
        return networkIO;
    }

	/**
	 * UI线程
	 * 
	 * Android 的MainThread
	 * UI线程不能做的事情这个都不能做
	 */
    public Executor mainThread() {
        return mainThread;
    }

    private static ScheduledExecutorService scheduledThreadPoolExecutor() {
        return new ScheduledThreadPoolExecutor(16, r -> new Thread(r, "scheduled_executor"), (r, executor) -> Log.e(TAG, "rejectedExecution: scheduled executor queue overflow"));
    }

    private static ExecutorService diskIoExecutor() {
        return new ThreadPoolExecutor(1, 1, 0L, TimeUnit.MILLISECONDS, new LinkedBlockingQueue<>(1024), r -> new Thread(r, "disk_executor"), (r, executor) -> Log.e(TAG, "rejectedExecution: disk io executor queue overflow"));
    }

    private static ExecutorService networkExecutor() {
        return new ThreadPoolExecutor(3, 6, 1000, TimeUnit.MILLISECONDS, new LinkedBlockingQueue<>(6), r -> new Thread(r, "network_executor"), (r, executor) -> Log.e(TAG, "rejectedExecution: network executor queue overflow"));
    }


    private static class MainThreadExecutor implements Executor {
        private final Handler mainThreadHandler = new Handler(Looper.getMainLooper());

        @Override
        public void execute(@NonNull Runnable command) {
            mainThreadHandler.post(command);
        }
    }
}

用法:

UI线程:

AppExecutors.getInstance().mainThread().execute(new Runnable() {
            @Override
            public void run() {
                //to do 
            }
        });

磁盘IO线程池:

AppExecutors.getInstance().diskIO().execute(new Runnable() {
            @Override
            public void run() {
                //to do
            }
        });

网络IO线程池:

AppExecutors.getInstance().networkIO().execute(new Runnable() {
            @Override
            public void run() {
                //to do
            }
        });

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值