线程池的使用

Posted jiatcode

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了线程池的使用相关的知识,希望对你有一定的参考价值。

线程池

1.介绍

多线程缺点:

  • 处理任务的线程创建和销毁都非常的耗时间并消耗资源
  • 多线程之间的切换也会非常耗时并消耗资源

采用线程池的好处

  • 使用时线程已经存在,消除了线程创建的消耗
  • 通过设置线程数目,防止资源不足

2.ThreadPoolExecutor构造函数参数

public ThreadPoolExecutor(int corePoolSize,
                          int maximumPoolSize,
                          long keepAliveTime,
                          TimeUnit unit,
                          BlockingQueue<Runnable> workQueue,
                          ThreadFactory threadFactory,
                          RejectedExecutionHandler handler) {
  • corePoolSize:线程池中核心线程数的最大值,核心线程不会被销毁

  • maximumPoolSize:线程池中能拥有的最大线程数

    • 当线程池中最大线程数大于最大核心线程数时,剩下的非核心线程可以被销毁
  • workQueue:用于缓存任务的阻塞队列

    • SynchronousQueue:内部只能包含一个元素,当线程池没有空闲的线程,插入元素到队列的线程会被阻塞,知道有空闲的线程向队列请求任务,入列操作才可以继续进行,然后空闲线程就可以得到元素
    • LinkedBockingQueue:链表实现的队列,可以是有界也可以是无界
  • 阻塞队列是指当核心线程无空闲时,有新的任务进来,就会先添加到阻塞队列等待核心线程空闲

  • 上述三者关系:新的任务进来,如果没有空闲线程

    • 正在运行的线程数<corePoolSize,则添加新的线程执行
    • 正在运行的线程数=corePoolSize,阻塞队列未满,添加到阻塞队列
    • 正在运行的线程数<maximumPoolSize,阻塞队列已经满了,创建新的线程执行
    • 正在运行的线程数<maximumPoolSize,阻塞队列已经满了,根据构造函数中的handler指定的策略来拒绝新的任务
  • keepAliveTime:表示空闲的线程存活的时间

  • unit:keepAliveTime的单位

  • handler:拒绝新任务采取的策略

    ThreadPoolExecutor.ThreadAbortPolicy() 抛出RejectedExecutionException
    ThreadPoolExecutor.CallerRunsPolicy() 由向线程池提交任务的线程来执行任务
    ThreadPoolExecutor.DiscardOldestPolicy() 抛弃最旧的任务(最先提交而没有得到执行的任务)
    ThreadPoolExecutor.DiscardPolicy() 抛弃当前的任务
  • threadFactory:指定线程创建工厂

3.四种常见的线程池

介绍创建线程的时候我们提到过,javaSE定义了一个Executors类简化我们创建线程池的过程,提供了四个线程池的创建方法

1.newCachedThreadPool

  • 可缓存线程池,线程池长度超过处理需要,可以灵活回收空余线程,若无可回收,则新建线程

  • 特点:

    • 工作线程的创建几乎没有限制(隐形限制为Integer.Max_value)
    • 空闲的工作线程可以会销毁,有新任务重新创建
    • 使用时要注意控制任务的数量,大量线程同时运行有可能造成系统瘫痪
  • 使用

    //创建线程池
    ExecutorService cachedThreadPool = Executors.newCacheThreadPool();
    //启动线程,cachedThreadPool线程只能通过实现Runnable接口的方式实现
    cachedThreadPool.execute(new Runnable(){
        public void run(){
           	………… 
        }
    });
    

2.newFixedThreadPool

  • 创建一个指定工作线程数量的线程池,每当提交一个任务就创建一个线程,达到线程池最大值则存入到池队列中

  • 优点:具有线程池提高程序效率和节省创建线程时所耗的开销

  • 缺点:线程池中的空闲线程不会自动销毁,线程池中没有可运行任务时,它不会释放工作线程,还有占用一定的系统资源,适合一直频繁有任务进行且任务量稳定的场景

  • 使用

    //3为自定义的线程数
    ExecutorService fixThreadPool = Executors.newFixedThreadPool(3);
    //使用方式和缓存线程池类似
    fixThreadPool.execute(new Runnable(){
        public void run(){
           	………… 
        }
    });
    

3.newSingleThreadExecutor

  • 创建一个单线程化的Executor,即只创建唯一的工作者线程来执行任务,他只会用唯一的工作线程来执行任务,保证所有任务按照指定顺序(FIFO,LIFO,优先级)执行。如果这个线程异常结束,会有另一个取代他,保证顺序执行
  • 单工作线程的最大特点是可保证顺序的执行各个任务,并且在任意给定的时间不会有多个线程是活动的。
  • 使用方式类似

4.newScheduleThreadPool

  • 定时线程:该方法创建一个定长的线程池,而且支持定时的以及周期性的任务执行

  • 使用

    //创建定长线程池
    ScheduleExecutorService scheduleThreadPool = Executors.scheduleThreadPool(5);
    //设置启动线程
    scheduleThreadPool.schedule(new Runnable(){
    	public void run(){
    		…………
    	}	
    },3,TimeUnit.SECONDS);
    //两个参数设置延迟时间,数值和单位,这里是3秒
    

以上是关于线程池的使用的主要内容,如果未能解决你的问题,请参考以下文章

Java——线程池

Java线程池详解

Java线程池详解

Java 线程池详解

线程池的使用场景和代码实现!

Java多线程-线程池的使用与线程总结(狂神说含代码)