• Android多线程和线程池


    目录

    多线程

    1  多线程的意义

    2  多线程的创建

    线程池

    1. 线程池的应用

    2. 线程池实现方式


    多线程

    1  多线程的意义

    (1)提高用户体验或者避免ANR(Application is not responding)

    (2)异步

           在应用程序中,有些情况下并不一定需要同步阻塞去等待返回结果,可以通过多线程来实现异步,如异步加载云端图片

    2  多线程的创建

        java 中有三种创建线程的方式,或者说四种:
    1. 继承 Thread 类实现多线程
      1. class MyThread extends Thread{
      2. @Override
      3. public void run() {
      4. super.run();
      5. Log.e("TAG:",Thread.currentThread().getName()+".run");
      6. }
      7. }
    2. 实现 Runnable 接口
      1. class MyRunnable implements Runnable{
      2. @Override
      3. public void run() {
      4. Log.e("TAG:",Thread.currentThread().getName()+".run");
      5. }
      6. }

    3. 实现 Callable 接口
      1. //创建线程
      2. class MyJob implements Callable{
      3. @Override
      4. public Boolean call() throws Exception {
      5. for (int i = 0; i < 5; i++) {
      6. System.out.println("I am running thread");
      7. }
      8. return true;
      9. }
      10. }
      11. //调用
      12. MyJob thread = new MyJob();
      13. // execute service,number of threads = 1
      14. ExecutorService service = Executors.newFixedThreadPool(1);
      15. // submit to execute
      16. Future result = service.submit(thread);
      17. boolean r = result.get(); // get result
      18. service.shutdownNow(); // shut down the service
      19. System.out.println(r);

    4. 通过线程池
      1. class MyTask implements Runnable{
      2. int index = 0;
      3. public MyTask(int i){this.index = i;}
      4. @Override
      5. public void run() {
      6. Log.e("TAG:",Thread.currentThread().getName()+" "+index);
      7. try { Thread.sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); }
      8. }
      9. }
      10. ExecutorService cacheThreadPool = Executors.newCachedThreadPool();
      11. ExecutorService fixedThreadPool = Executors.newFixedThreadPool(3);
      12. ExecutorService singleThreadPool = Executors.newSingleThreadExecutor();
      13. ScheduledExecutorService scheduledExecutorService =
      14. Executors.newSingleThreadScheduledExecutor();
      15. for(int i=1;i<=100;i++){
      16. singleThreadPool.execute(new MyTask(i));
      17. }

    线程池

    1. 线程池的应用

    (1)new Thread的弊端

           a)每次new Thread新建对象性能差

           b)线程缺乏统一管理,可能无限制新建线程,相互竞争,可能占用过多系统资源导致死机或内存溢出oom

           c)缺乏更多功能,如定时执行、定期执行、线程中断

    (2)线程池好处

            a)重用存在的线程,减少对象创建、消亡的开销,性能佳

            b)可有效控制最大并发线程数,提高系统资源的使用率,同时避免过多资源竞争,避免堵塞

            c)提供定时执行、定期执行、单线程、并发数控制等功能

    2. 线程池实现方式

    1:ThreadPoolExecutor 基本线程池


    2:FixedThreadPool (执行长期的任务,性能好很多)

             创建一个定长线程池,可控制线程最大并发数,超出的线程会在队列中等待。


    3:CachedThreadPool (适用于有大量需要立即执行的耗时少的任务的情况)

             创建一个可缓存线程池,如果线程池长度超过处理需要,可灵活回收空闲线程,若无可回收,则新建线程。


    4:SingleThreadPool(一个任务一个任务执行的场景是的单个的FixedThreadPool )

             创建一个单线程化的线程池,只会用唯一的工作线程来执行任务,保证所有任务按照指定的顺序(FIFO LIFO 优先级)执行。


    5:ScheduledThreadPool(周期性执行任务的场景)

            创建一个定长线程池,支持定时、周期性任务执行。


    1,新建线程池

    1. //创建基本线程池
    2. final ThreadPoolExecutor threadPoolExecutor = new
    3. ThreadPoolExecutor(3,5,1,TimeUnit.SECONDS,
    4. new LinkedBlockingQueue(100));
    5. /*创建fixed线程池,参数为核心线程数,
    6. 只有核心线程,无非核心线程,并且阻塞队列无界。
    7. 采用LinkedBlockingQueue
    8. */
    9. final ExecutorService fixedThreadPool = Executors.newFixedThreadPool(5);
    10. /*创建Cached线程池,没有核心线程,
    11. 只有非核心线程,并且每个非核心线程空闲等待的时间为60s,
    12. 采用SynchronousQueue队列。
    13. */
    14. final ExecutorService cachedThreadPool = Executors.newCachedThreadPool();
    15. /*创建Single线程池,只有一个核心线程,当被占用时,
    16. 其他的任务需要进入队列等待,采用LinkedBlockingQueue
    17. */
    18. final ExecutorService singleThreadExecutor = Executors.newSingleThreadExecutor();
    19. /*创建Scheduled线程池,延迟启动任务,
    20. 使用方法scheduledThreadPool.(runnable,10,TimeUnit.SECONDS);
    21. */
    22. final ScheduledExecutorService scheduledThreadPool = Executors.newScheduledThreadPool(3);

    2 加入线程,几种线程池的使用方法都一样,除了ScheduledExecutorService ;

    1. threadPoolExecutor.execute(new Runnable() {
    2. @Override
    3. public void run() {
    4. try {
    5. //处理相应事务
    6. } catch (InterruptedException e) {
    7. e.printStackTrace();
    8. }
    9. }
    10. });

    ScheduledExecutorService 使用方法

    1. //10是指延时10s启动
    2. scheduledThreadPool.(runnable,10,TimeUnit.SECONDS);

    3 其他方法

    1. 1.shutDown() 关闭线程池,不影响已经提交的任务
    2. 2.shutDownNow() 关闭线程池,并尝试去终止正在执行的线程
    3. 3.allowCoreThreadTimeOut(boolean value) 允许核心线程闲置超时时被回收
    4. 4.submit 一般情况下我们使用execute来提交任务,但是有时候可能也会用到submit,使用submit的好处是submit有返回值。
    5. 5.beforeExecute() - 任务执行前执行的方法
    6. 6.afterExecute() -任务执行结束后执行的方法
    7. 7.terminated() -线程池关闭后执行的方法


     

  • 相关阅读:
    FFmpeg开发笔记(九)Linux交叉编译Android的x265库
    origin中一组线单独设置颜色
    YoloV8改进策略:FastVit与YoloV8完美融合,重参数重构YoloV8网络(全网首发)
    人工智能基础_机器学习045_逻辑回归的梯度下降公式推导_更新公式---人工智能工作笔记0085
    UE5——源码阅读——3——引擎退出
    2022杭电多校八 1007-Darnassus(kruscal)
    面试中的这几个细节你一定要知道
    Elasticsearch基础知识点总结介绍
    【编程题】【Scratch四级】2021.03 程序优化
    u盘损坏无法读取怎么恢复数据?
  • 原文地址:https://blog.csdn.net/qq_14931305/article/details/126144129