Java线程池

Java线程池
一、Executors创建线程池
    newFixedThreadPool:固定指定线程数的线程池
    newSingleThreadExector:只有一个线程的线程池
    newCachedThreadPool:不限线程数上限的线程池,任何提交的任务都将立即执行
    newScheduledThreadPool:定时周期性执行的线程池

    任务类型:
    线程执行的任务,分为两种:1.实现Runnable接口;2.实现Callable接口;
        区别:
        Runnable:void Runnable.run();
        Callable:T Callable.call() throws Exception
        说明:Runnable没有返回值且不能抛出异常,Callable可以有返回值允许抛出异常。

    线程池提交任务的3种方式:
        返回结果:Future<T> submit(Callable<T> task);
        返回空:Future<?> submit(Runnable task),该方法有返回值,恒为空null
        不返回结果:void execute(Runnable command);

二、优化创建线程池
    避免直接使用Executors.newXXXThreadPool()的快捷方法创建线程池,因为Executors默认使用无界队列,容易导致OOM(内存不足)。所以需要明确指定使用有界队列(指定队列最大长度),且应当指明拒绝任务时发生的行为(策略)

    new ThreadPoolExecutor(corePoolSize,maximumPoolSize,keepAliveTime,unit,workQueue,threadFactory,handler);
    corePoolSize(核心线程数):线程池中常驻的线程数,线程池初始化时默认是没有线程的,当任务来临时才开始创建线程去执行任务。
    maximumPoolSize(最大线程数):在核心线程数的基础上,当workQueue队列填满时会创建多于corePoolSize且总线程数不超过maxPoolSize的线程
    keepAliveTime(非核线程空闲时长):当非核心线程的空闲时间该值时,会被自动终止回收掉。不过当corePoolSize=maxPoolSize时,keepAliveTime参数也就不起作用了(因为不存在非核心线程);
    unit:keepAliveTime的时间单位
    workQueue(工作队列):用于保存任务的队列,可以为无界、有界、同步移交三种队列类型之一,当池子里的工作线程数大于corePoolSize时,这时新进来的任务会被放到队列中
        SynchronousQueue(同步移交队列):队列不作为任务的缓冲方式,可以简单理解为队列长度为零
        LinkedBlockingQueue(无界队列):队列长度不受限制,当请求越来越多时(任务处理速度跟不上任务提交速度造成请求堆积)可能导致内存不足
        ArrayBlockintQueue(有界队列):队列长度受限,当队列满了就需要创建多余的线程来执行任务
    threadFactory(线程工厂):创建线程的工厂类,默认使用Executors.defaultThreadFactory(),也可以使用guava库的ThreadFactoryBuilder来创建
    handler(拒绝策略):线程池满载(队列数已满且线程数=maximunPoolSize)的时候,执行的拒绝接收任务的策略,取值有AbortPolicy、DiscardPolicy、DiscardOldestPolicy、CallerRunsPolicy
        AbortPolicy:默认方式,拒绝新任务并抛出RejectedExecutionException异常
        DiscardPolicy:什么也不做,直接忽略
        DiscardOldestPolicy:废弃队列中最老任务,接收当前任务。
        CallerRunsPolicy:直接由提交任务者执行这个任务
三、线程池的关闭
    shutdownNow():立即关闭线程池,正在执行中的及队列中的任务会被中断,同时该方法会返回被中断的队列中的任务列表
    shutdown():平滑关闭线程池,正在执行中的及队列中的任务能执行完成,后续进来的任务会被执行拒绝策略
    isTerminated():当正在执行的任务及对列中的任务全部都执行(清空)完就会返回true

四、线程池中线程数量定义
    线程池中,最核心的两个参数:核心线程数(corePoolSize)和最大线程数(maximumPoolSize)的数量设置
    核心线程数:
        CPU密集型任务:
            比如加解密、压缩、计算等,需大量消耗CPU资源的任务,最佳的线程数为 CPU 核心数的 1~2 倍
        耗时I/O型任务:
            比如数据库读取、文件读写、网络通信等,不会特别消耗CPU资源,但是总体耗时较多的任务
                线程数=CPU核心数*(1+平均等待时间/平均工作时间)
            单线程平均工作时间长,线程数相应减少。单线程平均工作时间越短,线程数相应增加。
五、线程工厂
    通过线程工厂给每个创建出来的线程设置极富业务含义的名字,实现业务上的肉眼区分

    通过第三方jar实现
    Spring下的CustomizableThreadFactory:Spring框架提供
        ThreadFactory springFactory = new CustomizableThreadFactory("spring-pool-");
        ExecutorService exec = new ThreadPoolExecutor(1, 1,0L, TimeUnit.MILLISECONDS,new LinkedBlockingQueue<Runnable>(100), springFactory);

    guava下的ThreadFactoryBuilder:Google 开源框架guava提供
        ThreadFactory guavaFactory = new ThreadFactoryBuilder().setNameFormat("guava-pool-").build();
        ExecutorService exec = new ThreadPoolExecutor(1, 1,0L, TimeUnit.MILLISECONDS,new LinkedBlockingQueue<Runnable>(100), guavaFactory);

    Apache下的commons-lang3 BasicThreadFactory:Apache提供。
        ThreadFactory apacheFactory = new BasicThreadFactory.Builder().namingPattern("apache-pool-").build();
        ExecutorService exec = new ThreadPoolExecutor(1, 1,0L, TimeUnit.MILLISECONDS,new LinkedBlockingQueue<Runnable>(100), apacheFactory);

    自定义ThreadFactory
        实现ThreadFactory接口,赋予线程名称属性。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值