1.Executors 提供四种线程池
1.1创建固定线程数目的线程池
创建使用固定线程数的FixedThreadPool,适用于为了满足资源管理的需求,而需要限制当前线程数量的应用场景,它适用于负载比较重的服务器。
public static ExecutorService newFixedThreadPool(int nThreads) { return new ThreadPoolExecutor(nThreads, nThreads, 0L, TimeUnit.MILLISECONDS, new LinkedBlockingQueue());//设定的阻塞队列是无界的 }
1.2创建一个“工作窃取(work stealing)”ForkJoinPool线程池
public static ExecutorService newWorkStealingPool(int parallelism) { return new ForkJoinPool (parallelism, ForkJoinPool.defaultForkJoinWorkerThreadFactory, null, true); }
1.3创建缓存线程池
创建一个会根据需要创建新线程的,适用于执行很多的短期异步任务的小程序,或者是负载较轻的服务器。
public static ExecutorService newCachedThreadPool() { return new ThreadPoolExecutor(0, Integer.MAX_VALUE, 60L, TimeUnit.SECONDS, new SynchronousQueue()); }
1.4创建单例线程池
适用于需要保证顺序地执行各个任务;并且在任意时间点,不会有多个线程是活动的应用场景。
public static ExecutorService newSingleThreadExecutor() { return new FinalizableDelegatedExecutorService (new ThreadPoolExecutor(1, 1, 0L, TimeUnit.MILLISECONDS, new LinkedBlockingQueue())); }
2.ThreadPoolExecutor自定义线程池
public ThreadPoolExecutor(int corePoolSize, int maximumPoolSize, long keepAliveTime, TimeUnit unit, BlockingQueueworkQueue, ThreadFactory threadFactory, RejectedExecutionHandler handler) { if (corePoolSize < 0 || maximumPoolSize <= 0 || maximumPoolSize < corePoolSize || keepAliveTime < 0) throw new IllegalArgumentException(); if (workQueue == null || threadFactory == null || handler == null) throw new NullPointerException(); this.acc = System.getSecurityManager() == null ? null : AccessController.getContext(); this.corePoolSize = corePoolSize; this.maximumPoolSize = maximumPoolSize; this.workQueue = workQueue; this.keepAliveTime = unit.toNanos(keepAliveTime); this.threadFactory = threadFactory; this.handler = handler; }
参数说明
1、corePoolSize:核心线程池的大小,如果核心线程池有空闲位置,这是新的任务就会被核心线程池新建一个线程执行,执行完毕后不会销毁线程,线程会进入缓存队列等待再次被运行。
2、maximunPoolSize:线程池能创建最大的线程数量。如果核心线程池和缓存队列都已经满了,新的任务进来就会创建新的线程来执行。但是数量不能超过maximunPoolSize,否侧会采取拒绝接受任务策略,我们下面会具体分析。
3、keepAliveTime:非核心线程能够空闲的最长时间,超过时间,线程终止。这个参数默认只有在线程数量超过核心线程池大小时才会起作用。只要线程数量不超过核心线程大小,就不会起作用。
4、unit:时间单位,和keepAliveTime配合使用。
TimeUnit.DAYS; //天 TimeUnit.HOURS; //小时 TimeUnit.MINUTES; //分钟 TimeUnit.SECONDS; //秒 TimeUnit.MILLISECONDS; //毫秒 TimeUnit.MICROSECONDS; //微妙 TimeUnit.NANOSECONDS; //纳秒
5、workQueue:缓存队列,用来存放等待被执行的任务。
- ArrayBlockingQueue;
- LinkedBlockingQueue;
- SynchronousQueue;
6、threadFactory:线程工厂,用来创建线程,一般有三种选择策略。
public class ThreadFactoryMain implements ThreadFactory{ private final String groupName; private AtomicInteger nextId = new AtomicInteger(1); public ThreadFactoryMain(String groupName) { this.groupName = "ThreadFactoryMain -" + groupName + "-worker-"; } @Override public Thread newThread(@NotNull Runnable r) { String threadName = groupName + nextId.incrementAndGet(); Thread thread = new Thread(null,r,threadName,0); return thread; } public static void main(String[] args){ ThreadPoolExecutor threadPoolExecutor = new ThreadPoolExecutor(10,50, 60L, TimeUnit.SECONDS, new LinkedBlockingQueue(20), new ThreadFactoryMain("zs.zhou")); Stream.iterate(0,n->n+1).limit(10).forEach(i->threadPoolExecutor.submit(new Runnable() { @Override public void run() { System.out.println(Thread.currentThread().getName() + " ::: --- " + i); } })); System.out.println("end"); threadPoolExecutor.shutdown(); } }
7、handler:拒绝处理策略,线程数量大于最大线程数就会采用拒绝处理策略,四种策略为
- ThreadPoolExecutor.AbortPolicy:丢弃任务并抛出RejectedExecutionException异常。
- ThreadPoolExecutor.DiscardPolicy:也是丢弃任务,但是不抛出异常。
- ThreadPoolExecutor.DiscardOldestPolicy:丢弃队列最前面的任务,然后重新尝试执行任务(重复此过程)
- ThreadPoolExecutor.CallerRunsPolicy:由调用线程处理该任务