【JUC】线程池—Executor

创建线程池可以分为三种方式:

1. 通过ThreadPoolExecutor的构造方法,创建ThreadPoolExecutor的对象,即一个线程池对象;

此构造方法,一共7个参数,5个必须参数,2个带有默认值的参数;详细后面说;

传送:https://www.cnblogs.com/mussessein/p/11654022.html

2. 通过Executors返回的线程池对象;

这种方法创建的常用线程池为4种,还可以创建ForkJoinPool对象;

可以说是封装好的方法,通过Executors的4种常用静态方法,返回4种已经封装好的ThreadPoolExecutor线程池对象;

传送:https://www.cnblogs.com/mussessein/p/11654120.html

3. ForkJoinPool并发框架

将一个大任务拆分成多个小任务后,使用fork可以将小任务分发给其他线程同时处理,使用join可以将多个线程处理的结果进行汇总;这实际上就是分治思想。

Executor类(尽量不使用此方法,而是使用ThreadPoolExecutor类)

Executors 返回的线程池对象的弊端如下:

  1. FixedThreadPool 和 SingleThreadPool : 允许的请求队列长度为 Integer.MAX_VALUE ,可能会堆积大量的请求,从而导致 OOM 。

  2. CachedThreadPool 和 ScheduledThreadPool : 允许的创建线程数量为 Integer.MAX_VALUE ,可能会创建大量的线程,从而导致 OOM 。

只要用于返回ExecutorService对象

四种方法都返回一个ExecutorService的实现类ThreadPoolExecutor的实例对象,创建四种不同的线程池。

public static ExecutorService newFixedThreadPool(int nThreads) {
    return new ThreadPoolExecutor(nThreads, nThreads,
                                    0L, TimeUnit.MILLISECONDS,
                                    new LinkedBlockingQueue<Runnable>());
}
  • 创建固定数目线程的线程

  • 缓存队列:LinkedBlockingQueue:无界阻塞队列,队列最大值为Integer.MAX_VALUE,如果任务提交速度持续大余任务处理速度,会造成队列大量阻塞。

public static ExecutorService newCachedThreadPool() {
     return new ThreadPoolExecutor(0, Integer.MAX_VALUE,
                                   60L, TimeUnit.SECONDS,
                                   new SynchronousQueue<Runnable>());
}
  • 创建一个可缓存的线程池

  • 缓存队列:SynchronousQueue 同步队列

public static ExecutorService newSingleThreadExecutor() {
    return new FinalizableDelegatedExecutorService(new ThreadPoolExecutor
                                                   (1, 1,
                                                    0L, TimeUnit.MILLISECONDS,
                                                new LinkedBlockingQueue<Runnable>()));
}
  • 创建一个单线程化的线程池,其中corePoolSize,maximumPoolSize,都为1,即只有一个线程在运行。

public static ScheduledExecutorService newScheduledThreadPool(int corePoolSize) {
    return new ScheduledThreadPoolExecutor(corePoolSize);
}
  • 创建一个支持定时及周期性的任务执行的线程池

演示:

使用线程池的一般步骤:

  1. 创建线程:Runnable实现类、Callable实现类

  2. 调用Executors类的静态工厂方法创建一个ExecutorService的实例对象,一个线程池创建成功

  3. 调用ExecutorService对象的submit方法提交线程

  4. shutdown方法关闭线程池。

    public static void main(String[] args){
        // 创建一个具有固定线程数6的线程池
        ExecutorService pool= Executors.newFixedThreadPool(6);
        // 使用lambda创建Runnable对象
        Runnable target=()->{
            for (int i=0;i<20;i++){
                System.out.println(Thread.currentThread().getName()+"---i值:"+i);
            }
        };
        // 向线程池提交两个线程
        pool.submit(target);
        pool.submit(target);
        //关闭线程池
        pool.shutdown();
    }
原文地址:https://www.cnblogs.com/mussessein/p/11654120.html