线程调度-线程池

一、new Thread弊端

    1.每次new Thread新建对象,性能查。
    2.线程缺乏统一管理,可能无限制的新建线程,相互竞争,有可能占用过多系统资源导致司机或OOM( Out Of Memory)。
    3.缺少更多的功能,如更多执行、定期执行、线程中断。

二、线程池的好处

    1.重用存在的线程,减少对象创建、消亡的开销,性能好。
    2.可有效控制最大并发线程数,提高系统资源利用率,同时可以避免过多资源竞争,避免阻塞。
    3.提供定时执行、定期执行、单线程、并发数控制等高级功能。

三、线程池相关的类

    1.ThreadPoolExecutor
        ThreadPoolExecutor中含有三个参数
        1)corePoolSize:核心线程数量。
        2)maximumPoolSize:最大线程数。
        3)workQueue:阻塞队列,存储等待执行的任务,很重要,会对线程池运行过程产生重大影响。 常用的有三种队列, SynchronousQueue , LinkedBlockingDeque , ArrayBlockingQueue
        4)KeepAliveTime:非核心线程没有任务执行时最多保持多长时间终止。
        5)unit:keepAliveTime的时间单位。
        6)threadFactory:线程工厂,用来创建线程。
        7)rejectHandler:拒绝处理任务时的策略。
        8)线程池规则
            下面都假设任务队列没有大小限制:
            a.如果线程数量<=核心线程数量,那么直接启动一个核心线程来执行任务,不会放入队列中。           
             b. 如果线程数量>核心线程数,但<=最大线程数,并且任务队列是LinkedBlockingDeque的时候,超过核心线程数量的任务会放在任务队列中排队。
             c. 如果线程数量>核心线程数,但<=最大线程数,并且任务队列是SynchronousQueue的时候,线程池会创建新线程执行任务,这些任务也不会被放在任务队列中。这些线程属于非核心线程,在任务完成后,闲置时间达到了超时时间就会被清除。        
            d. 如果线程数量>核心线程数,并且>最大线程数,当任务队列是LinkedBlockingDeque,会将超过核心线程的任务放在任务队列中排队。也就是当任务队列是LinkedBlockingDeque并且没有大小限制时,线程池的最大线程数设置是无效的,他的线程数最多不会超过核心线程数。
            e. 如果线程数量>核心线程数,并且>最大线程数,当任务队列是SynchronousQueue的时候,会因为线程池拒绝添加任务而抛出异常。
             任务队列大小有限时
           a. 当LinkedBlockingDeque塞满时,新增的任务会直接创建新线程来执行,当创建的线程数量超过最大线程数量时会抛异常。
           b. SynchronousQueue没有数量限制。因为他根本不保持这些任务,而是直接交给线程池去执行。当任务数量超过最大线程数时会直接抛异常。
        9)线程池的使用:
            a.execute():提交任务,交给线程池执行。
            b.submit():提交任务,能够返回结果(execute+Future)。
            c.shutdown():关闭线程池,等待任务都执行完毕。
            d.shutdownNow():关闭线程池,不等待任务执行完毕,会中断正在执行的线程。
            e.getTaskCount():线程池已执行和未执行的任务总数。
            f.getCompletedTaskCount():已完成的任务数量。
            g.getPoolSize():线程池当前的线程数量。
            h.getActiveCount():当前线程池中正在执行任务的线程数量。
    2.Executor框架提供的四种线程池
        executor框架提供了四种线程池,其内部都是返回一个ThreadPoolExecutor对象。
       1)Executors.newCachedThreadPool: 创建一个可缓存线程池,如果线程池长度超过处理需要,可灵活回收空闲线程,若无可回收,则新建线程。(线程最大并发数不可控制)
        2) Executors.newFixedThreadPool:创建一个定长线程池,可控制线程最大并发数,超出的线程会在队列中等待。
        3) Executors.newScheduledThreadPool:创建一个定长线程池,支持定时及周期性任务执行。
        4) Executors.newSingleThreadPool:创建一个单线程化的线程池,它只会用唯一的工作线程来执行任务,保证所有任务按照指定顺序(FIFO, LIFO, 优先级)执行。

    3.线程池的合理配置
        1)CPU密集型任务,就需要尽量压榨CPU,参考值可以尽量设置为CPU数量+1。
        2)IO密集型任务,参考值可以设置为2*CPU数量。
注:使用线程池也需要慎重,有些场景下因为线程池中任务调度所造成的开销,可能会使我们得不偿失。
    


你可能感兴趣的:(线程调度-线程池)