• Executors常见的线程池创建以及其问题


    采用工厂类的方式来创建线程池,主要有五种:

    newCachedThreadPool(可缓存的线程池)

           他在创建新线程时如果有可重用的线程,则重用他们,否则创建一个新的线程并添加到线程池中,因此对于执行时间短的任务来说,该线程池能够恒大成都的重用线程从而提高了系统的性能;在线程池的keepAliveTime时间超过60秒后该线程会被终止并从缓存中移除,因此在无线程任务执行时,它将不会占用系统的线程资源。底层使用的是ThreadPoolExecutor的构造函数,其中参数corePoolSize为0,maxinumPoolSize的为Integer.MAX_VALUE,阻塞队列采用的是同步队列SynchronousQueue。创建方式如下:

    ExecutorService cachedThreadPool = Exectors.newCachedThreadPool();

    newFixedThreadPool(固定大小的线程池)

          创建固定大小的线程池,并将线程资源放在队列中进行循环利用,若处于活动状态的线程数量大于等于核心线程池的数量,则将任务放在阻塞队列中排队,直到有可用的线程资源。创建如下:

    ExecutorService fixedThreadPool = Exectors.newFixedThreadPool(3);   //三个线程的线程池

    newScheduledThreadPool(可做任务调度的线程池,周期性执行任务)

          可用于定时调度的线程池,可设置在指定的延迟时间后执行或者定期执行某个线程任务。

    周期性执行任务的例子:(每五秒钟执行一次任务)

    import java.text.SimpleDateFormat;
    import java.util.Calendar;
    import java.util.Date;
    import java.util.concurrent.*;
    
    /**
     * 周期性执行任务
     */
    public class ThreadPool {
        public static void main(String[] args) {
            ScheduledExecutorService scheduledExecutorService = Executors.newScheduledThreadPool(5); //五个线程的线程池
            scheduledExecutorService.scheduleAtFixedRate(new RunnablePool(),10,5000,TimeUnit.MILLISECONDS); //10毫秒后开始执行,每五秒钟执行一次
        }
        static  class RunnablePool implements Runnable{
            @Override
            public void run() {
                Calendar instance = Calendar.getInstance();
                Date time = instance.getTime();
    
                String format = new SimpleDateFormat("HH:mm:ss").format(time);
                System.out.println("线程"+Thread.currentThread().getName()+"执行时间为:"+format);
            }
        }
    }

    newSingleThreadPool(单个线程的线程池)

          保证线程池中永远有且只有一个可用的线程,在该线程停止或者发生异常时,该线程池会启动一个新的线程来代替该线程继续执行任务。底层使用的是ThreadPoolExecutor的构造函数,其中参数corePoolSize和maxinumPoolSize的值都是1,阻塞队列采用的是无界的队列LinkedBlockingQueue。可以满足按照任务提交顺序进行执行的场景。

    ExecutorService singleThreadPool = Exectors.newSingleThreadPool();

    newWorkStealingPool(足够大小的线程池,JDK1.8新增的)

            持有足够的线程的线程池来达到快速运算的目的。内部通过使用多个队列来减少各个线程调度产生的竞争。足够的线程是指JDK根据当前的线程的运行需求向操作系统申请足够的线程,来保证任务的快速执行,最大程度的使用系统资源,提高并发的计算效率,省去了用户根据CPU资源估算并行度的过程。当然也可以自定义线程的并发数。

    注意!

           Executors尽管在创建线程池中很方便,但是FixedThreadPool和SingleThreadPool :允许的请求队列长度为Integer.MAX_VALUE,可能会堆积大量的请求,从而导致00M。   CachedThreadPool和ScheduledThreadPool :允许的创建线程数量为Integer.MAX_VALUE,可能会创建大量的线程,从而导致OOM。在阿里的开发手册中,Executors创建线程池的方法是不被允许的,意味着这种方法要慎用,推荐直接使用ThreadPoolExecutor来创建线程池,自己设置最大核心线程,最大线程数和阻塞队列,拒绝策略以及保持存活时间等。

  • 相关阅读:
    201871010135
    201871010135-张玉晶 实验三 结对项目——《D{0-1}KP 实例数据集算法实验平台》项目报告
    201871010135-张玉晶 实验二 个人项目——《背包问题{0-1}》项目报告
    201871010135-张玉晶 实验一 软件工程准备 ——软件工程及markdown编辑器的初步认识
    张玉晶 201871010135《面向对象程序设计(java)》课程学习总结
    201871010135 张玉晶 《面向对象程序设计(java)》第十七周学习总结
    201871010135 张玉晶《面向对象程序设计(java)》第十六周学习总结
    201871010135 张玉晶《面向对象程序设计(java)》第十五周学习总结
    201871010135 张玉晶《面向对象程序设计(java)》第十四周学习总结
    201871010135 张玉晶《面向对象程序设计(java)》第十三周学习总结
  • 原文地址:https://www.cnblogs.com/128-cdy/p/13171076.html
Copyright © 2020-2023  润新知