Java线程池

线程池

线程池ThreadPoolExecutor继承关系

在这里插入图片描述

创建的关键参数及含义
  • corePoolSize:线程池中核心线程数,即使是闲置的也会存在,除非allowCoreThreadTimeOut被设置为true(需配合keepAliveTime>0使用)
  • maximumPoolSize:线程池中允许的最大线程数。FixedThreadPoolcorePoolSizecachedThreadPoolInteger.MAX_VALUESingleThread为1
  • keepAliveTime:非核心线程闲置后允许存活的时间,一般为0。如果allowCoreThreadTimeOut为true,闲置核心线程也会被销毁
  • unit:keepAliveTime的时间单位,一般为毫秒TimeUnit.MILLISECONDS
  • workQueue:任务队列。task被提交后未执行时保存所在的队列,类型为阻塞队列BlockingQueue,一般为LinkedBlockingQueueArrayBlockingQueue
    • 当小于corePoolSize的线程在执行时,task不会入队,而是创建一个新核心线程执行
    • 当等于corePoolSize的核心线程在执行并且队列非满时,task会入队
    • 当等于corePoolSize的核心线程在执行并且队列满并且正在执行的总线程不大于maximumPoolSize时,会创建一个新非核心线程执行
    • 当队列满并且当前执行的总线程达到maximumPoolSize时,会根据rejectedExecutionHandler执行拒绝策略。
  • threadFactory:创建新线程的工厂类。一般使用默认的工厂类Executors.defaultThreadFactory()
  • rejectedExecutionHandler:当任务队列满时的拒绝策略。下为ThreadPoolExecutor中默认的四种拒绝策略。
    • DiscardPolicy():直接拒绝,不抛出异常
    • DiscardOldestPolicy():丢弃任务队列队首任务(等待时间最长的任务),将新任务加入。
    • AbortPolicy():直接拒绝,抛出RejectedExecutionException异常(默认)
    • CallerRunsPolicy():如果当前线程池没有关闭,将新任务在调用所在线程直接执行(直接调用r.run())而不是线程池调度.
线程池的种类及作用
  • newFixedThreadPool:创建容纳固定线程数的线程池,适用大负载的服务器

    public class Executors {
        public static ExecutorService newFixedThreadPool(int nThreads) {
            return new ThreadPoolExecutor(nThreads, nThreads,
                                          0L, TimeUnit.MILLISECONDS,
                                          new LinkedBlockingQueue<Runnable>());
        }
    }
    
    
  • newCachedThreadPool:创建可容纳Integer.MAX_VALUE大小的线程池,空闲线程的存货时间为60秒,提交新任务时,不会排成队列(SynchronousQueue)而是创建新的线程执行。适用小负载的服务器,避免直接使用此方法,因为其maximumPoolSize过大

    public static ExecutorService newCachedThreadPool() {
        return new ThreadPoolExecutor(0, Integer.MAX_VALUE,
                                      60L, TimeUnit.SECONDS,
                                      new SynchronousQueue<Runnable>());
    }
    
  • newSingleThreadExecutor:与fixedThreadPool相似,创建只能容纳一个线程的线程池

    public static ExecutorService newSingleThreadExecutor() {
        return new FinalizableDelegatedExecutorService
            (new ThreadPoolExecutor(1, 1,
                                    0L, TimeUnit.MILLISECONDS,
                                    new LinkedBlockingQueue<Runnable>()));
    }
    
  • ScheduledExecutorService:创建一个可以延后一段时间或定期执行任务的线程池

    // Executors
    public static ScheduledExecutorService newScheduledThreadPool(int corePoolSize) {
            return new ScheduledThreadPoolExecutor(corePoolSize);
    }
    
    // ScheduledThreadPoolExecutor
    public ScheduledThreadPoolExecutor(int corePoolSize) {
            super(corePoolSize, Integer.MAX_VALUE,
                  DEFAULT_KEEPALIVE_MILLIS, MILLISECONDS,	//10秒
                  new DelayedWorkQueue());
    }
    
  • newWorkStealingPool(属于ForkJoinPool):大任务拆分(fork)成小任务,并行执行,合并(join)小任务结果。参考线程池ForkJoinPool简介

submit和execute方法有什么区别

参考Java线程池系列之execute和submit区别

  • submit是AbstractExecutorService的方法,而execute是顶层接口Executor的方法,由ThreadPoolExecutor实现。

  • submit可以接收CallableRunnable类型的参数,execute只能接收Runnable类型的参数。submit方法内部也会调用execute方法,不过AbstractExecutorService自己没有实现而是交给ThreadPoolExecutor实现,AbstractExecutorService在调用execute前后做了一系列封装,使得submit能够接收CallableRunnable参数并返回Future

  • submit如果线程抛出异常会将异常暂存不会立即抛出,等到调用get()方法时才抛出,execute线程发生异常会立即抛出

    public class Example {
        public static void diffSubmitAndExecute() throws ExecutionException, InterruptedException {
    
            ExecutorService executor = Executors.newFixedThreadPool(6);
            
            // execute会立即抛出
    		executor.execute(() -> {throw new IllegalStateException("execute手动异常");});
            
            // submit在submit时不会立即抛出,而是调用get时抛出
            Future<String> res = executor.submit(() -> {
                throw new IllegalStateException("submit手动异常");
            });
            // 抛出异常
            Object o = res.get();
        }
    }
    
    
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值