java线程学习,java线程API学习ThreadPoolExecutor

    先介绍一下,多线程大师Doug Lea。也就是java.util.concurrent包的作者。
    0d968f235cec2a0ead34ded9java线程API学习ThreadPoolExecutorjava线程学习
    如果IT的历史,是以人为主体串接起来的话,那么肯定少不了Doug Lea。这个鼻梁挂着眼镜,留着德王威廉二世的胡子,脸上永远挂着谦逊腼腆笑容,服务于纽约州立大学Oswego分校计算器科学系的老大爷。
    说他是这个世界上对Java影响力最大的个人,一点也不为过。因为两次Java历史上的大变革,他都间接或直接的扮演了举足轻重的脚色。一次是由JDK 1.1到JDK 1.2,JDK1.2很重要的一项新创举就是Collections,其Collection的概念可以说承袭自Doug Lea于1995年发布的第一个被广泛应用的collections;一次是2004年所推出的Tiger。Tiger广纳了15项JSRs(Java Specification Requests)的语法及标准,其中一项便是JSR-166。JSR-166是来自于Doug编写的util.concurrent包。
    值得一提的是: Doug Lea也是JCP (Java小区项目)中的一员。
    Doug是一个无私的人,他深知分享知识和分享苹果是不一样的,苹果会越分越少,而自己的知识并不会因为给了别人就减少了,知识的分享更能激荡出不一样的火花。《Effective JAVA》这本Java经典之作的作者Joshua Blosh便在书中特别感谢Doug是此书中许多构想的共鸣板,感谢Doug大方分享丰富而又宝贵的知识。
    下面是正经的。
    ThreadPoolExecutor继承自ExecutorService。将提交执行的任务在内部线程池中的可用线程中执行。一般来说,用Executors.newCachedThreadPool(创建自动增加或减少容量的线程池)或Executors.newFixedThreadPool(创建固定容量的线程池)或Executors.newSingleThreadExecutor(单独线程的线程池)。

    · 关于corePoolSize和maximumPoolSize

    ThreadPoolExecutor会根据corePoolSize和maximumPoolSize的值调整线程池中线程的数量。当通过ThreadPoolExecutor.execute方法向线程池提交一个新的任务时,如果线程池当前线程数量小于corePoolSize,就算有线程空闲,也会在创建一个线程执行这个任务;如果线程池当前线程数量大于corePoolSize又小于maximumPoolSize,只有当可用线程不够的时候才会创建新的线程。如果不希望系统动态增减线程数量,则将corePoolSize和maximumPoolSize数值设置为一样的值。如果将maximumPoolSize设置为一个特别大的值如Integer.MAX_VALUE,则ThreadPoolExecutor成为了一个能够容纳大量并发任务的线程池。一般来说corePoolSize和maximumPoolSize是在构造ThreadPoolExecutor对象时设置好的,当仍然可以调用ThreadPoolExecutor.setCorePoolSize和ThreadPoolExecutor.setMaximumPoolSize方法修改这两个属性。

    · 关于线程创建

    线程池中的线程是由ThreadFactory创建。如果不特别指定,会使用Executors.defaultThreadFactory创建位于同一个线程组,相同优先级(NORM_PRIORITY)的非守护线程。如果由你来指定ThreadFactory,你可以定制线程名字,线程组,优先级,是否为守护线程等属性。

    · 线程的存活时间

    如果线程池中当前线程数大于corePoolSize,如果超过keepAliveTime后仍然没有使用,则超出部分会被终止掉。当需要更多线程的时候,再重新创建。这个属性也可以通过setKeepAliveTime修改。

    · 列队

    BlockingQueue用来管理被提交进来等待执行的任务。是否进入queue和线程池的容量有关。如果线程池中运行的线程小于corePoolSize,新的任务不会进入queue而是在新建的线程中执行。如果线程池中运行的线程大于或等于corePoolSize,更倾向于将任务加入queue而不是新建线程。如果queue满了,则创建新的线程执行任务。如果线程数量大雨了maximumPoolSize,任务被拒绝。
    以下是三种列队的策略:
    1.直接传递:这也是缺省的实现使用SynchronousQueue,直接将队列中的任务转交给线程。如果将任务提交给队列时没有足够的线程处理这个任务,新的线程会被创建。一般来说需要将maximumPoolSize设置为最大以避免出现拒绝新提交来的任务的情况出现。当然了如果任务提交的速度大过了处理任务的速度会引起线程池中线程无限增长的问题。
    2.无限队列:使用不限制容量的队列LinkedBlockingQueue。当所有corePoolSize的线程都在忙碌时新提交进来的任务在队列中等待。也就是说,即使线程池中的线程数小于maximumPoolSize,也不会有新的线程被创建(maximumPoolSize参数失效)。这种策略适用于提交来的各个任务相互独立的场景。例如,一个网页服务来说,使用这种策略能平滑瞬间突发的访问请求。
    3.有限队列:使用有限队列防止将maximumPoolSize设置为最大时,资源耗尽的问题。调整队列大小和maximumPoolSize之间关系比较就变得重要了。使用大容量队列和较小的线程数可以降低CPU和资源的使用但会导致效率低下。小容量的队列需要相对较大的maximumPoolSize配合,增加了CPU调度线程的负担。

    · 任务拒绝

    调用ThreadPoolExecutor.execute方法提交新任务是,如果线程池已经被停止运行或线程数量、队列数量已满。
Tags:  java线程池 java线程 java多线程 api创建线程 java线程学习

延伸阅读

最新评论

发表评论