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

原文地址:https://www.cnblogs.com/128-cdy/p/13171076.html