• 多线程-Executors和Executor,线程池


    jdk1.5之前,所有的线程都是需要自己手动创建的,由jvm销毁,当请求过多的时候,频繁的创建和销毁线程是非常浪费资源的。jdk1.5为此做了优化,提供了

    java.util.concurrent

    包,该包下有个 Executor 接口,官方解释为:

    执行已提交的 Runnable 任务的对象。此接口提供一种将任务提交与每个任务将如何运行的机制(包括线程使用的细节、调度等)分离开来的方法。通常使用 Executor 而不是显式地创建线程。

    很明显,有这个这个东西,我们不需要自己手动 new Thread了。程序员只需要专注于任务就可以了,然后把任务交给executor,由他帮我们执行任务。

    因此,我们可以非常自然的想到一个东西,那就是 线程池,ThreadPoolExecutor就是该接口的具体实现类。

    我们的具体的线程池实现类。

    public class ThreadPoolExecutor extends AbstractExecutorService


    实现了通用的管理线程的方法。
    public abstract class AbstractExecutorService implements ExecutorService


    ExecutorService抽象了基本的管理线程的方法,如提交任务,关闭任务。
    public interface ExecutorService extends Executor


    而线程池有几个主体,线程管理器(线程池本身),工作线程(workThread)任务(runnable),等待队列。

    简单来说,线程管理器维护一定数量的工作线程,将我们提交的任务交由工作线程完成,当池中没有空闲的工作线程时,交给等待队列中去。等待队列可以是先进先出,先进后出,具体策略由你自己来决定。当等待队列也慢了的时候,我们

    当创建线程池时几个参数包含了线程池的一切

    corePoolSize:
    核心线程池数,线程池默认的工作线程数,线程池创建时,默认为0,只有来一个任务才创建一个线程。

    maximumPoolSize:
    线程池允许的最多线程数,当等待队列满了之后,这个参数才有意义。

    keepAliveTime:
    当池中的线程数大于核心线程数时,多余的线程在销毁之前会等待指定时间。

    unit:
    多余的线程等待的时间单位。


    workQueue:
    当核心线程数全部都在运行任务时,再次来的任务将被放到该等待队列中。此队列仅保持由 execute 方法提交的 Runnable 任务。
    举个栗子来说名线程池根据参数运行的流程:
    corePoolSize:5
    maximumPoolSize:15(包含corePoolSize)
    keepAliveTime:2
    unit:秒
    workQueue:数组型等待队列,最大的等待数为50

    1.当我创建5个线程时,线程池将会一一创建核心线程数,
    2.当第6个任务来临,而前面5个任务还没有完成是,线程池中没有线程了,那么线程池将会把这个任务放到任务workQueue中。
    3.当第56个线程来临时,而核心线程还在运行,而workQueue中也已经饱和。此时,线程池会多创建一个线程来运行多出来的那一个任务
    (具体哪一个任务根据你的策略来)。但是池中的线程数不能超过maximumPoolSize,包含核心数。
    4.当第66个任务来临的时候,池中已经有15个线程在运行任务了,等待队列中也已经有50个线程在等待,因此 15+50=65 是ok的,但是再来一个66的
    话那就不ok了,线程池直接回拒接你,抛出 RejectedExecutionException 错误。
    测试代码如下:
    public class Worker extends Thread {

    private int i = 0;

    @Override
    public void run() {

    while(i==0){
    i++;
    try {
    Thread.currentThread().sleep(2000);
    } catch (InterruptedException e) {
    e.printStackTrace();
    }
    System.out.println(Thread.currentThread().getName()+" run...");
    }

    }
    }


    //等待队列最大任务数为50
    ArrayBlockingQueue arrayBlockingQueue = new ArrayBlockingQueue<Runnable>(50);
    //核心线程数:5 最大线程数:15 多余线程存活时间:2秒
    ThreadPoolExecutor threadPoolExecutor = new ThreadPoolExecutor(5,15,2,TimeUnit.SECONDS,arrayBlockingQueue);
    // threadPoolExecutor.prestartAllCoreThreads();
    System.out.println("池中的当前线程数 :" + threadPoolExecutor.getPoolSize());

    //创建56个任务。
    for(int i = 0 ; i < 65; i ++){
    threadPoolExecutor.execute(new Worker());
    }
    System.out.println("==================over===============");

    ArrayBlockingQueue<Runnable> blockingQueue = (ArrayBlockingQueue)threadPoolExecutor.getQueue();


    System.out.println("池中的当前线程数 :" + threadPoolExecutor.getPoolSize());
    System.out.println("曾经同时位于池中的最大线程数 :" + threadPoolExecutor.getLargestPoolSize());
    System.out.println("等待队列中的任务数:" + blockingQueue.size());


    输出:
    池中的当前线程数 :0
    ==================over===============
    池中的当前线程数 :15
    曾经同时位于池中的最大线程数 :15
    等待队列中的任务数:50
    pool-1-thread-2  run...
    pool-1-thread-5  run...
    .....
    Executors类中包含了很多静态方法创建多种不同类型的线程池。
    1.创建可伸缩线程池。
    2.创建定长线程池。
    3.创建定长线程池,支持执行定制和周期性任务。
    3.创建单例线程的线程池。
    参考资料:
    http://www.importnew.com/19011.html
    http://blog.csdn.net/hsuxu/article/details/8985931
    http://cuisuqiang.iteye.com/blog/2019372
    ---------------------
    作者:helianus
    来源:CSDN
    原文:https://blog.csdn.net/helianus/article/details/78304733
    版权声明:本文为博主原创文章,转载请附上博文链接!

  • 相关阅读:
    chapter1 Qt入门
    base64加密解密
    vue+CryptoJS+cookie实现保存账号密码
    js计时器
    Elenent ui中的表单校验规则、自定义校验规则、预验证功能
    js获取文件后缀
    js中如何将有字符串转换为数组,或将数组转换为字符串
    vue-router
    Vue项目纯前端导出word文档
    async/await
  • 原文地址:https://www.cnblogs.com/GarfieldEr007/p/10230855.html
Copyright © 2020-2023  润新知