• Android 多线程的几种实现方式(二)-- Executor


    4. Executor 线程实现

    
            Runnable runnable = new Runnable() {
                @Override
                public void run() {
                    System.out.println("runnable 线程开始执行");
                }
            };
            Executor executor = Executors.newCachedThreadPool();
            executor.execute(runnable);
            executor.execute(runnable);
            executor.execute(runnable);
            
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12

    4.1 Executor 简介

    Executor 给他一个 Runnable,他就能自动很安全的帮你把这个线程执行完毕
    Executor 通过创建线程池的方式来管理线程
    Executor 有五种创建线程池的方式,其中 newCachedThreadPool() 是一种非常简单的线程池创建方式
    Executor 有两种结束方式,shutDown()shutDownNow()

    1. shutDown 会将当前正在执行的和排队中的线程执行完毕后结束,并且不允许有新的线程加入到待执行队列中
    2. shutDownNow 会立即结束执行,采取的是一种比较安全的结束方式:interrupt()

    4.2 Executor 中 其他几种创建线程池的方式

    4.2.1 Executor 中的第一种线程池创建方式 newCachedThreadPool()
    
    	public static ExecutorService newCachedThreadPool() {
            return new ThreadPoolExecutor(0, Integer.MAX_VALUE,
                                          60L, TimeUnit.SECONDS,
                                          new SynchronousQueue<Runnable>());
        }
        
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    newCachedThreadPool() 的实现:

    newCachedThreadPool 中,会直接返回一个 ThreadPoolExecutor,这里解释一下创建 ThreadPoolExecutor 的几个参数:

    	/**
    	 * @param corePoolSize 代表默认线程数,或者说最低线程数,也就是此线程池创建后里面立马会有几个线程的数量
    	 * @param maximumPoolSize 代表最大线程数,超过此线程数量则排队等待执行,排队线程放入最后一个参数中
    	 * @param keepAliveTime 表示默认线程数量外的其他线程在处于空闲状态下,被回收前需要等待的时间
    	 * @param unit 表示第三个时间值的单位
    	 * @param workQueue 用于盛放多余线程的线程队列
    	 */
    	ThreadPoolExecutor(int corePoolSize,
                                  int maximumPoolSize,
                                  long keepAliveTime,
                                  TimeUnit unit,
                                  BlockingQueue<Runnable> workQueue)
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    1. 第一个参数代表默认线程数,或者说最低线程数,也就是此线程池创建后里面立马会有几个线程的数量
    2. 第二个参数代表最大线程数,超过此线程数量则排队等待执行,排队线程放入最后一个参数中
    3. 第三个参数表示默认线程数量外的其他线程在处于空闲状态下,被回收前需要等待的时间
    4. 第四个参数表示第三个时间值的单位
    5. 第五个参数用于盛放多余线程的线程队列

    例:

    假如说传入的值分别为 5,20,10L,TimeUnit.SECONDS,new SynchronousQueue< Runnable>()

    则表示,创建一个默认数量为 5 的线程池,这个线程池最多允许 20 条线程同时工作,如果超过 20 个则存放进队列中等待这 20 个线程腾出位置,每个线程执行完毕都去队列中取新的任务并执行,如果队列中没有新的任务,则线程等待 10 秒,如果 10 后仍然没有新的任务,则线程会被回收,一直回收到只剩余 5 个线程

    4.2.1 Executor.newSingleThreadExecutor()
    
    	public static ExecutorService newSingleThreadExecutor() {
            return new FinalizableDelegatedExecutorService
                (new ThreadPoolExecutor(1, 1,
                                        0L, TimeUnit.MILLISECONDS,
                                        new LinkedBlockingQueue<Runnable>()));
        }
        
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    通过前两个参数可以看出,这是创建单线程的线程池,也就是说这个线程池中只有一个线程,并且最多也只能有一个线程,应用场景比较少。

    4.2.2 Executor.newFixedThreadPool()
    
    	public static ExecutorService newFixedThreadPool(int nThreads) {
            return new ThreadPoolExecutor(nThreads, nThreads,
                                          0L, TimeUnit.MILLISECONDS,
                                          new LinkedBlockingQueue<Runnable>());
        }
        
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    创建固定数量线程的线程池,通过前两个参数可以看出,传入的参数被同时应用中前两个参数中,这就意味着我创建一个线程池,里面的默认线程数和最大线程数一致,并且不能扩容、不被回收,一直放在那里,表面上可能比较合理,但实际的应用场景也很少

    在处理瞬时爆发性任务时会能用得到,例:

    
            Runnable precessImageRunner = new Runnable() {
                @Override
                public void run() {
                    System.out.println("开始处理图片了,我很耗时,,,,");
                }
            };
            
            List<Bitmap> bitmaps = new ArrayList<>();
            
            ExecutorService fixedExecutor = Executors.newFixedThreadPool(30);
            
            for (Bitmap bitmap : bitmaps) {
                fixedExecutor.execute(precessImageRunner);
            }
            
            fixedExecutor.shutdown();
            
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18

    fixedExecutor.shutdown() 来防止永远不回收造成资源浪费的情况

    4.2.3 Executor.newScheduledThreadPool()

    创建一个延迟的线程池

    4.2.4 Executor.newSingleThreadScheduledExecutor()

    创建一个延迟的单线程线程池

    总结

    以上就是 Executor 的简介及 Executor 五种创建线程的方式,你学废了吗?

    复习一遍:

    
    		//  Executor 五种创建线程的方式
    		
            Executors.newCachedThreadPool();
            
            Executors.newSingleThreadExecutor();
            
            Executors.newFixedThreadPool();
            
            Executors.newScheduledThreadPool();
            
            Executors.newSingleThreadScheduledExecutor();
            
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
  • 相关阅读:
    elementUi——table表格中内容超过2行后,省略号...展示,鼠标悬停展示全部
    无需编写一行代码,实现任何方法的流量防护能力
    【毕业季】这四年一路走来都很值得——老学长の忠告
    魔众题库系统 v8.8.0 公式编辑升级,注册站内信和邮件,手机Banner支持视频背景
    OCR文字识别软件对于硬件的哪方面需求较高?
    2022年了,软件测试已经饱和了?
    腾讯mini项目-【指标监控服务重构】2023-08-06
    两大产品上线“粤复用”,赋能大数据智能行业发展
    css 雷达扫描图
    C++-map和set
  • 原文地址:https://blog.csdn.net/qq_35178391/article/details/126016462