zoukankan      html  css  js  c++  java
  • 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来创建线程池,自己设置最大核心线程,最大线程数和阻塞队列,拒绝策略以及保持存活时间等。

  • 相关阅读:
    header头参数 确定该文件类型
    phpexcel 使用说明
    杂七杂八 各种小知识
    php 后知后觉
    限制SSH登录失败次数
    DES和AES密码之间的区别 & 对称加密算法DES、3DES和AES 原理总结
    加密算法(DES,AES,RSA,MD5,SHA1,Base64)比较和项目应用
    加密算法学习总结---DES-CBC加密算法 & 分组加密的四种模式
    Linux下进程间通信方式——共享内存
    fork()+pipe() --> 父子进程间通过管道通信 Linux系统编程pipe()
  • 原文地址:https://www.cnblogs.com/128-cdy/p/13171076.html
Copyright © 2011-2022 走看看