【Java】并发之线程池

先看一段我们熟悉的代码:

  1. for (int i = 0; i < 100; i++) {  
  2.     Thread thread = new Thread(new OneTask(i));  
  3.     thread.start();  
  4. }  

其中,OneTask为Runnable接口的实现类。

思考一个问题:当要异步执行大量任务时,比如1000个任务,通过这种方法,就要创建1000个线程。大量线程的创建、销毁,并发执行与线程调度,是一笔很大的性能开销。另外,这么多线程难以很好地管理,有多少任务正在执行、多少任务已经执行完成,无法得知。

线程池,可以很好地处理这些问题。从Java中实现线程池的类为ThreadPoolExecutor。上面的代码,修改为:

  1. LinkedBlockingQueue<Runnable> workQueue = new LinkedBlockingQueue<Runnable>(90);  
  2. ThreadPoolExecutor threadPoolExecutor = new ThreadPoolExecutor(51020, TimeUnit.SECONDS, workQueue);  
  3. for (int i = 0; i < 100; i++) {  
  4.     threadPoolExecutor.execute(new OneTask(i));  
  5. }  

ThreadPoolExecutor调用execute方法来“执行”任务(Runnable)实例,其实,说“提交”任务实例更为合理,因为不一定就能立即执行,只是提交到线程池,由线程池来调度执行。

来看一下ThreadPoolExecutor构造方法:

  1. public ThreadPoolExecutor(int corePoolSize,   
  2.                     int maximumPoolSize,   
  3.                     long keepAliveTime,   
  4.                     TimeUnit unit,   
  5.                     BlockingQueue<Runnable> workQueue);  

corePoolSize:线程池核心线程数大小,所谓“核心线程”,即在线程池中必不可少的,即使该线程负责执行的任务执行完毕,也不可少销毁自己,必须留在池中,以等待执行新的任务。

maximumPoolSize:线程池最大线程数大小,要注意,最大线程数总会大于或等于核心线程数。为什么会有大于?因为,除了核心线程外,线程池还可以创建一些新线程加入池中,这些新线程不同于核心线程,它们完成任务,空闲一定的时间后便会销毁掉。而这个时间,由下面两个参数决定。

keepAliveTime:非核心线程空闲时保留在池中多长时间,除非有新任务要求它去执行,否则过了这段时间,该线程会销毁掉。TimeUnit为时间单位类,如传参TimeUnit.SECONDS,表示keepAliveTime的单位为秒。

workQueue:一个BlockingQueue类型的参数,我们暂且简单地理解为一个队列。线程池使用这个队列来装载等待的任务。上面代码中,使用了BlockingQueue接口的一个实现类LinkedBlockingQueue,它的构造方法有一个参数capacity,决定了线程池等待队列的容量,即最多可以允许多少个任务加入等待队列。

下面分析下线程池创建、提交任务、任务等待、执行任务的过程。

a. 当ThreadPoolExecutor刚构造时,池中是还没有线程的。

b. 当调用execute()方法提交任务时,线程池会创建一个线程,来执行该任务,此时,线程池当前的线程数(pool size)为1。

c. 继续提交任务,继续创建线程(假设前面的任务都还没有这么快执行完),池中线程数递增1,依此类推。当达到corePoolSize个时,就不再创建新线程,新提交的任务就会进入等待队列,等到corePoolSize个线程中,有某个线程执行完任务时,等待队列中的任务才得以进入线程池中执行。

d.(继续假设前面的任务都还没有这么快执行完)继续提交任务,继续加入等待队列,当超出了等待队列所能容纳的最大限度(BlockingQueue的capacity值)时。前面说的maximumPoolSize参数要发挥作用了。当设置的maximumPoolSize值大于corePoolSize值,则此时线程池会创建新线程来执行该任务,线程池中线程数递增1。当线程池中的线程数达到了maximumPoolSize个,就不能再创建了,否则会报RejectedExecutionException异常。

e.线程执行完一个任务后,会从等待队列中取出新任务,然后执行新任务,这个过程,等待队列的任务数会减少。当线程池也渐渐执行完所有任务后,corePoolSize个的x线程(核心线程)继续存活不会销毁。而那些非核心线程(最多maximumPoolSize-corePoolSize个),过了keepAliveTime时间后便会被销毁。


Executors类是一工厂类,提供了一些创建常用ThreadPoolExecutor的方法。贴一下这些方法的源码,会更容易理解。

a. 创建固定个数的线程池执行器:

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

b. 创建单个线程的线程池执行器:

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

单线程执行器,可保证按顺序地执行任务。

c.创建缓存的线程池执行器:
  1. public static ExecutorService newCachedThreadPool() {  
  2.     return new ThreadPoolExecutor(0, Integer.MAX_VALUE,  
  3.                                   60L, TimeUnit.SECONDS,  
  4.                                   new SynchronousQueue<Runnable>());  
  5. }  
缓存线程执行器,执行大量的耗时短的任务,能很好地改善性能。

@容新华技术博客 - http://blog.csdn.net/rongxinhua - 原创文章,转载请注明出处


Java异步并发线程池是一种用于管理和执行多线程异步任务的机制。通过使用线程池,可以有效地控制系统资源,并提高并发性能。核心线程数是线程池中一直存在的线程数量,它们准备就绪并等待异步任务的执行。可以使用ExecutorService接口的实现类Executors来创建线程池,例如使用newFixedThreadPool方法创建一个固定大小的线程池,如下所示:ExecutorService service = Executors.newFixedThreadPool(10); \[1\] 关于Java异步并发线程池的更多信息,可以参考以下资源: - 参考1:https://wenku.baidu.com/view/a9cdf1c09889680203d8ce2f0066f5335a81672a.html - 参考2:https://www.cnblogs.com/weilx/p/16329743.html \[3\] #### 引用[.reference_title] - *1* *2* [Java中的异步与线程池](https://blog.csdn.net/weixin_47409774/article/details/123610455)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^insert_down28v1,239^v3^insert_chatgpt"}} ] [.reference_item] - *3* [Java异步并发线程池](https://blog.csdn.net/qq_36330274/article/details/127229455)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^insert_down28v1,239^v3^insert_chatgpt"}} ] [.reference_item] [ .reference_list ]
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值