欢迎访问昆山宝鼎软件有限公司网站! 设为首页 | 网站地图 | XML | RSS订阅 | 宝鼎邮箱 | 后台管理


新闻资讯

MENU

软件开发知识
原文出处: CarpenterLee

结构一个线程池为什么需要几个参数?假如制止线程池呈现OOM?RunnableCallable的区别是什么?本文将对这些问题一一解答,同时还将给出利用线程池的常见场景和代码片断。

基本常识

Executors建设线程池

Java中建设线程池很简朴,只需要挪用Executors中相应的便捷要领即可,好比Executors.newFixedThreadPool(int nThreads),可是便捷不只埋没了巨大性,也为我们埋下了潜在的隐患(OOM,线程耗尽)。

Executors建设线程池便捷要领列表:

要领名 成果
newFixedThreadPool(int nThreads) 建设牢靠巨细的线程池
newSingleThreadExecutor() 建设只有一个线程的线程池
newCachedThreadPool() 建设一个不限线程数上限的线程池,任何提交的任务都将当即执行

小措施利用这些快捷要领没什么问题,对付处事端需要恒久运行的措施,建设线程池应该直接利用ThreadPoolExecutor的结构要领。没错,上述Executors要领建设的线程池就是ThreadPoolExecutor

ThreadPoolExecutor结构要领

Executors中建设线程池的快捷要领,实际上是挪用了ThreadPoolExecutor的结构要领(按时任务利用的是ScheduledThreadPoolExecutor),该类结构要领参数列表如下:

// Java线程池的完整结构函数
public ThreadPoolExecutor(
  int corePoolSize, // 线程池恒久维持的线程数,纵然线程处于Idle状态,也不会接纳。
  int maximumPoolSize, // 线程数的上限
  long keepAliveTime, TimeUnit unit, // 高出corePoolSize的线程的idle时长,
                                     // 高出这个时间,多余的线程会被接纳。
  BlockingQueue<Runnable> workQueue, // 任务的列队行列
  ThreadFactory threadFactory, // 新线程的发生方法
  RejectedExecutionHandler handler) // 拒绝计策

竟然有7个参数,很无奈,结构一个线程池确实需要这么多参数。这些参数中,较量容易引起问题的有corePoolSizemaximumPoolSizeworkQueue以及handler

  • corePoolSizemaximumPoolSize配置不妥会影响效率,甚至耗尽线程;
  • workQueue配置不妥容易导致OOM;
  • handler配置不妥会导致提交任务时抛出异常。
  • 正确的参数配置方法会在下文给出。

    线程池的事情顺序

    If fewer than corePoolSize threads are running, the Executor always prefers adding a new thread rather than queuing.
    If corePoolSize or more threads are running, the Executor always prefers queuing a request rather than adding a new thread.
    If a request cannot be queued, a new thread is created unless this would exceed maximumPoolSize, in which case, the task will be rejected.

    corePoolSize -> 任务行列 -> maximumPoolSize -> 拒绝计策

    Runnable和Callable

    可以向线程池提交的任务有两种:RunnableCallable,二者的区别如下:

    1. 要领签名差异,void Runnable.run()V Callable.call() throws Exception
    2. 是否答允有返回值,昆山软件开发,Callable答允有返回值
    3. 是否答允抛出异常,Callable答允抛出异常。

    Callable是JDK1.5时插手的接口,作为Runnable的一种增补,劳务派遣管理系统,答允有返回值,答允抛出异常。

    三种提交任务的方法:

    提交方法 是否体贴返回功效
    Future<T> submit(Callable<T> task)
    void execute(Runnable command)
    Future<?> submit(Runnable task) 否,固然返回Future,可是其get()要领老是返回null

    如何正确利用线程池

    制止利用无界行列

    不要利用Executors.newXXXThreadPool()快捷要领建设线程池,因为这种方法会利用无界的任务行列,为制止OOM,我们应该利用ThreadPoolExecutor的结构要领手动指定行列的最大长度:

    ExecutorService executorService = new ThreadPoolExecutor(2, 2, 
                    0, TimeUnit.SECONDS, 
                    new ArrayBlockingQueue<>(512), // 利用有界行列,制止OOM
                    new ThreadPoolExecutor.DiscardPolicy());

    明晰拒绝任务时的行为