java常用的六种线程池

更新时间:2020-09-11 11:44:27 点击次数:1280次
一 、FixedThreadPool
顾名思义就是固定容量的线程池,它的容量是固定的,通过构造方法传递线程池运行线程的数量。

//第一个参数:传递一个int线程的大小,核心线程数
//2.最大线程数,=核心线程数。3.最大的存活时间4.时间单位
//5.阻塞队列
public static ExecutorService newFixedThreadPool(int nThreads) {
        return new ThreadPoolExecutor(nThreads, nThreads,
                                      0L, TimeUnit.MILLISECONDS,
                                      new LinkedBlockingQueue<Runnable>());
                  
public ThreadPoolExecutor(int corePoolSize,
                              int maximumPoolSize,
                              long keepAliveTime,
                              TimeUnit unit,
                              BlockingQueue<Runnable> workQueue) {
        this(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue,
             Executors.defaultThreadFactory(), defaultHandler);
    }

创建一个线程池这个线程会创建核心线程数,因为最大线程数等于核心线程数(一般的当阻塞队列满员时,就会创建线程以达到最大线程数),所以当不会额外创建线程,所以keepAliveTime也为0。
然后,看这个阻塞队列,用的是LinkedBlockingQueue,链表的形式,它是没有容量限制的,所以所有进入线程池的线程都会进入里面等待,等待核心线程有空位。在this()里面有两个多余的参数是线程工厂的初始化和拒绝策略。
适用:执行长期任务。

二 、CachedThreadPool
public static ExecutorService newCachedThreadPool() {
        return new ThreadPoolExecutor(0, Integer.MAX_VALUE,
                                      60L, TimeUnit.SECONDS,
                                      new SynchronousQueue<Runnable>());
    }

我们可以看到核心数为0,最大为MAX_VALUE = 0x7fffffff,也就是2的31次方-1,基本上相当于无限大60L, TimeUnit.SECONDS表示线程不工作的时候60s释放线程,而后面这个阻塞队列属于手把手交易的一种方式,有线程直接交给消费,里面没有存储线程的内存。
适用:执行很多短期异步的小程序或者负载较轻的服务器(来任务用任务,没有任务删除线程)

三 、ScheduledThreadPool
支持定时和周期性的执行任务

public ScheduledThreadPoolExecutor(int corePoolSize) {
        super(corePoolSize, Integer.MAX_VALUE, 0, NANOSECONDS,
              new DelayedWorkQueue());
    }

使用的阻塞队列为DelayedWorkQueue()。支持周期性的执行任务

public ScheduledFuture<?> schedule(Runnable command,
                                       long delay,
                                       TimeUnit unit)
 public ScheduledFuture<?> scheduleAtFixedRate(Runnable command,
                                                  long initialDelay,
                                                  long period,
                                                  TimeUnit unit)  
public ScheduledFuture<?> scheduleWithFixedDelay(Runnable command,
                                                     long initialDelay,
                                                     long delay,
                                                     TimeUnit unit)
                                                                                     

每隔一段时间执行一次任务
period 两次任务的间隔数
delay一次任务执行结束,到下一次任务的延迟
适用于:周期性任务
四、SingleThreadExecutor
new ThreadPoolExecutor(1, 1,
                 0L, TimeUnit.MILLISECONDS,
                 new LinkedBlockingQueue<Runnable>())

核心和最大线程数为1,并且用的链式阻塞队列(无限制个数),能保证任务执行的顺序等于提交的顺序。
适用:于一个任务一个任务执行的场景

五、SingleThreadScheduledExecutor
new ScheduledThreadPoolExecutor(1)
 super(corePoolSize, Integer.MAX_VALUE, 0, NANOSECONDS,
              new DelayedWorkQueue());
1
2
3
核心1,最大Integer.MAX_VALUE,使用的是延迟任务队列和第三种ScheduledThreadPool有点相似,是一种特列ScheduledThreadPool是自定义核心线程数,但单例时间线程池是必须为1的。
适用:周期,一个一个运行三和四的结合

五、ForkJoinPool(拆分汇总)

斐波那契额数列的一个应用

import edu.princeton.cs.algs4.StdOut;

import java.util.concurrent.ExecutionException;
import java.util.concurrent.ForkJoinPool;
import java.util.concurrent.ForkJoinTask;
import java.util.concurrent.RecursiveTask;

public class FeiBoNaQie extends RecursiveTask<Integer> {

    int n;
    public FeiBoNaQie(int n) {
        this.n = n;
    }
    @Override
    protected Integer compute() {
        if(n<=1)return n;
        FeiBoNaQie f1=new FeiBoNaQie(n-1);
        f1.fork();
        FeiBoNaQie f2=new FeiBoNaQie(n-2);
        f2.fork();
        return f1.join()+f2.join();
    }

    public static void main(String[] args) throws ExecutionException, InterruptedException {
          ForkJoinPool pool=new ForkJoinPool();
          for(int i=0;i<10;i++){
              ForkJoinTask<Integer> task=pool.submit(new FeiBoNaQie(i));
              System.out.println(task.get());
        }
    }
}

这就就和递归很相似,不过就是分线程,每个线程里面有一个双端队列,队列是先进先出FIFO,存储分裂出的子任务,,适合数的遍历,最优路径搜索等场景,听说里面会相互协作 work-stealing,队列任务之间能相互帮忙,避免闲着没事做,从而提高效率。没看源码。

本站文章版权归原作者及原出处所有 。内容为作者个人观点, 并不代表本站赞同其观点和对其真实性负责,本站只提供参考并不构成任何投资及应用建议。本站是一个个人学习交流的平台,网站上部分文章为转载,并不用于任何商业目的,我们已经尽可能的对作者和来源进行了通告,但是能力有限或疏忽,造成漏登,请及时联系我们,我们将根据著作权人的要求,立即更正或者删除有关内容。本站拥有对此声明的最终解释权。

回到顶部
嘿,我来帮您!