龙空技术网

学会java这几个线程池的使用,会使得你的程序效率提升十倍

愚公要移山 1087

前言:

目前朋友们对“java池的作用”大体比较看重,同学们都需要学习一些“java池的作用”的相关知识。那么小编在网摘上汇集了一些有关“java池的作用””的相关内容,希望看官们能喜欢,我们一起来学习一下吧!

有时候在服务器处理客户端连接的时候,一个客户端我们都会创建一个线程去处理,但是我们可能会纳闷,难道有一万个客户端连接,我们也要创建一万个线程分别去处理嘛?这显然是不合理的。因此我们就用到了线程池这个概念。这篇文章就来好好的分析一下java中的四种线程池。

一、引言

1、new一个Thread的弊端

新建一个线程池其实是有很多弊端的,什么弊端呢?这里总结了三条。

(1) 每次new Thread新建对象性能差。因为每次都会创建一个对象。这是既耗时又消耗资源的。

(2) 线程缺乏统一管理,可能会造成自锁,或者是内存溢出。

(3)缺乏更多功能,如定时执行、定期执行、线程中断。

2、使用线程池的好处

相比new Thread,Java提供的四种线程池的好处在于:

(1)重用存在的线程,减少对象创建、消亡的开销,性能佳。

(2)可有效控制最大并发线程数,提高系统资源的使用率,同时避免过多资源竞争,避免堵塞。

(3)提供定时执行、定期执行、单线程、并发数控制等功能。

既然线程池这么好,我们就来看看如何使用吧。

二、线程池的使用

1、框架



通过这张图我们可以看到,最下面的Excutors是整个线程池的核心。他里面提供了大量的创建线程池的方法。再往上走ThreadPoolExcutor就是一个线程池。在这个类里面定义了线程池的工作原理。

2、ThreadPoolExcutor

在这个类里面主要是通过这样一个方法参数来实现的线程池原理。



这里面的参数有必要好好地讲一下:

(1)int corePoolSize(核心线程数):

线程池新建线程的时候,如果当前线程总数小于corePoolSize,则新建的是核心线程,核心线程默认情况下会一直存活在线程池中;如果设置了 allowCoreThreadTimeOut 为 true,那么核心线程如果不干活的话,超过一定时间,就会被销毁掉。

(2)int maximumPoolSize(线程池能容纳的最大线程数量):

线程总数 = 核心线程数 + 非核心线程数。

(3)long keepAliveTime(非核心线程空闲存活时长):

非核心线程空闲时长超过该时长将会被回收

(4)TimeUnit unit 空闲线程的存活时间

在这里表示的是时间的单位,比如说秒。

(5)BlockingQueue workQueue(任务队列):

当所有的核心线程都在干活时,新添加的任务会被添加到这个队列中等待处理,如果队列满了,则新建非核心线程执行任务。常用的workQueue类型:

①SynchornousQueue:这里表示接到新任务,直接交给线程处理,如果其他的线程都在工作,那就创建一个新的线程来处理这个任务。

②LinkedBlockingQueue:这里表示接到新任务,如果当前线程数小于核心线程数,则新建核心线程处理任务;如果当前线程数等于核心线程数,则进入队列等待。

③ArrayBlockingQueue:这里表示接到新任务,如果没有达到核心线程数,则新建核心线程执行任务,如果达到了,则入队等候,如果队列已满,则新建非核心线程执行任务,又如果总线程数到了 maximumPoolSize,并且队列也满了,则发生错误。

④DelayQueue:这里表示接到新任务,先入队,达到了指定的延时时间,才执行任务。

6.ThreadFactory threadFactory(线程工厂):

用来创建线程池中的线程。

7.RejectedExecutionHandler handler(拒绝策略):

指的之超过了maximumPoolSize,无法再处理新的任务,就会直接拒绝,提供了以下 4 种策略:

①AbortPolicy:默认策略,在拒绝任务时,会抛出RejectedExecutionException。

②CallerRunsPolicy:只要线程池未关闭,该策略直接在调用者线程中,运行当前的被丢弃的任务。

③DiscardOldestPolicy:该策略将丢弃最老的一个请求,也就是即将被执行的任务,并尝试再次提交当前任务。

④DiscardPolicy:该策略默默的丢弃无法处理的任务,不予任何处理



OK,有了这个最核心的线程池,我们就可以看看在这个ThreadPoolExcutor之上,Excutor为我们提供的几种线程池。

3、四种线程池

Executors提供的线程池配置方案

(1)构造一个固定线程数目的线程池,配置的corePoolSize与maximumPoolSize大小相同,同时使用了一个无界LinkedBlockingQueue存放阻塞任务,因此多余的任务将存在再阻塞队列,不会由RejectedExecutionHandler处理



(2)构造一个缓冲功能的线程池,配置corePoolSize=0,maximumPoolSize=Integer.MAX_VALUE,keepAliveTime=60s,以及一个无容量的阻塞队列 SynchronousQueue,因此任务提交之后,将会创建新的线程执行;线程空闲超过60s将会销毁



(3)构造一个只支持一个线程的线程池,配置corePoolSize=maximumPoolSize=1,无界阻塞队列LinkedBlockingQueue;保证任务由一个线程串行执行



(4)构造有定时功能的线程池,配置corePoolSize,无界延迟阻塞队列DelayedWorkQueue。



其实对于线程池这块的知识点,真的是很多,这篇文章的出发点在于会根据自己的业务场景能够熟练的使用。希望对你有帮助


标签: #java池的作用