Java 多线程的几种实现方式(二)-- 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);
        

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>());
    }
    

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. 第五个参数用于盛放多余任务的线程队列

例:

假如说传入的值分别为 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>()));
    }
    

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

4.2.2 Executor.newFixedThreadPool()

	public static ExecutorService newFixedThreadPool(int nThreads) {
        return new ThreadPoolExecutor(nThreads, nThreads,
                                      0L, TimeUnit.MILLISECONDS,
                                      new LinkedBlockingQueue<Runnable>());
    }
    

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

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


        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();
        

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();
        

你可能感兴趣的:(Java,多线程与线程安全,android基础进阶,android,java,jvm)