• ThreadPool study


    线程池浅析

    线程池顾名思义就是放线程的池子 Thread Pool。

    那么为什么要有线程池呢?有些时候系统需要处理非常多的执行时间很短的请求,如果每一个请求都开启一个新的线程,则系统创建销毁线程的开销就太大了,甚至在创建和销毁线程的时间比任务的执行时间还长。

    使用new Thread() 会有如下缺点:

    1.创建和销毁线程耗费大量系统资源;

    2.每次new Thread() 缺乏线程管理,被称为野线程,而且可以无限制创建,之间相互竞争,会导致过多占用系统资源导致系统瘫痪。

    3.不利于扩展,如定期执行,定时执行,线程中断。

    线程池主要解决了两个问题:

           1.通过重用线程,达到减少每个线程创建和销毁的性能开销。

           2.对线程进行一些维护,比如定时开始,周期执行,并发控制等。

           3.可控制最大并发线程数,提高系统资源的使用率,同时避免过多资源竞争。

    Executor:JDK1.5引入,内部使用线程池机制,在java.util.cocurrent包下,Executor框架包括:线程池,Executor,Executors,ExecutorService,CompletionService,Future,Callable,ThreadPoolExecutor等。

    Executors:工厂类 创建线程池

    1.newFixedThreadPool
    public static ExecutorService newFixedThreadPool(int nThreads) {
    
        return new ThreadPoolExecutor(nThreads, nThreads,
    
                                      0L, TimeUnit.MILLISECONDS,
    
                                      new LinkedBlockingQueue<Runnable>());
    
    }

    创建一个固定数目的线程池,内部维持一个无界的队列,当所有的线程都在处于活动状态时提交了其他任务,则新任务将在队列中等待直到线程可用。

    2.newCachedThreadPool
    public static ExecutorService newCachedThreadPool() 
    {
    
        return new ThreadPoolExecutor(0, Integer.MAX_VALUE,
    
                                      60L, TimeUnit.SECONDS,
    
                                      new SynchronousQueue<Runnable>());
    
    }

    创建一个根据需要创建新线程的线程池,但在可用时将重新使用以前构造的线程。

    该线程池适用于执行许多短暂异步任务的程序,调用execute会重用以前构造的线程,如果没有可用的线程,则会创建新的线程,并将该线程添加到该池中,未使用60秒的线程将被终止并从缓存中删除。因此,长时间保持闲置的池将不会消耗任何资源。

    3.newSingleThreadExecutor
    public static ExecutorService newSingleThreadExecutor() {
    
        return new FinalizableDelegatedExecutorService
    
            (new ThreadPoolExecutor(1, 1,
    
                                    0L, TimeUnit.MILLISECONDS,
    
                                    new LinkedBlockingQueue<Runnable>()));
    
    }

    创建一个使用无界队列运行单个工作线程的执行程序,等效于newFixedThreadPool(1)

    4.newScheduledThreadPool
    public static ScheduledExecutorService newScheduledThreadPool(int corePoolSize) {
    
        return new ScheduledThreadPoolExecutor(corePoolSize);
    
    }

    创建一个线程池,可以调度命令在给定的延迟之后运行,或定期执行。

    scheduleAtFixedRate(Runnable command,
                                                     long initialDelay,
                                                     long delay,
                                                     TimeUnit unit);

    首次执行在 initialDelay 之后,第二次 执行时间为 initialDelay+delay*1 ….

    scheduleWithFixedDelay(Runnable command,
                                                     long initialDelay,
                                                     long delay,
                                                     TimeUnit unit);

    第一次的执行时间为 当前时间+ initialDelay,第二次为第一次执行结束时间+delay

    ExecutorService 的submit() 和 execute()区别:

    1.入参不同 submit可以接收Runnable或者Callable ,execute方法只能接收Runnable

    2.返回值 submit 有返回值 而 execute没有返回值

    3.submit方便处理Exception  Future.get抛出的异常

    Runnable和Callable的区别

    Callable接口中的call方法是有返回值的,泛型可任意制定,但是Runnable接口中run方法是没有返回值的。

    ThreadPoolExecutor:JDK提供的Executors工具类中创建的线程无法满足使用场景时,则需要手动配置和调优,则用到该池。

    public ThreadPoolExecutor(int corePoolSize,
    
                              int maximumPoolSize,
    
                              long keepAliveTime,
    
                              TimeUnit unit,
    
                              BlockingQueue<Runnable> workQueue) {
    
        this(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue,
    
             Executors.defaultThreadFactory(), defaultHandler);
    
    }

    参数详解:

    corePoolSize:核心线程数

    maximumPoolSize:最大线程数

    keepAliveTime:最大空闲时间

    BlockingQueue:使用的任务队列

                   ArrayBlockingQueue:底层是数组的定长任务队列,必须制定长度,可设置是               否公平锁。默认先进先出

                   LinkedBlockingQueue:底层为链表的可定长任务队列,不指定长度则为无界,             可设置公平锁,默认为先进先出

                   SynchronousQueue:同步的没有缓冲的任务队列,只有当线程将队列中的take走之后,才能新加进来任务

    defaultHandler:该参数代表的是拒绝策略,默认为AbortPolicy

    可以通过设置改变

    /**
     * ThreadPoolExecutor.AbortPolicy() 
    抛出java.util.concurrent.RejectedExecutionException异常
     
    * ThreadPoolExecutor.CallerRunsPolicy() 使用主线程跑当前任务
     
    * ThreadPoolExecutor.DiscardOldestPolicy() 抛弃旧的任务
     
    * ThreadPoolExecutor.DiscardPolicy() 抛弃当前的任务
     
    */
  • 相关阅读:
    用css3弹性盒子模型实现九宫格布局
    css布局之左中右结构总结
    内联块inline-block的垂直间隙问题
    Jquery选择器 讲解
    U大师装系统
    陈伟:软件趋势——云物移大智
    asp网站发布步骤总结
    MYfirst
    ASP.net 利用From实现上传文件
    【ASP.NET Core CentOS 发布】(四)在CentOS上安装.NET Core运行时、部署到CentOS
  • 原文地址:https://www.cnblogs.com/zhaiyt/p/9910978.html
Copyright © 2020-2023  润新知