java常用的六种线程池

tech2022-09-20  143

FixedThreadPool(固定线程池)CachedThreadPool(缓存线程池)ScheduledThreadPool(预定/已安排的线程池)SingleThreadExecutorSingleThreadScheduledExecutorForkJoinPool

一 、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,最大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()); } } } 0 1 1 2 3 5 8 13 21 34

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

最新回复(0)