Java 线程池_动力节点Java学院整理

发布时间 - 2026-01-11 01:23:19    点击率:

线程池

系统启动一个新线程的成本是比较高的,因为它涉及到与操作系统的交互。在这种情况下,使用线程池可以很好的提供性能,尤其是当程序中需要创建大量生存期很短暂的线程时,更应该考虑使用线程池。

与数据库连接池类似的是,线程池在系统启动时即创建大量空闲的线程,程序将一个Runnable对象传给线程池,线程池就会启动一条线程来执行该对象的run方法,当run方法执行结束后,该线程并不会死亡,而是再次返回线程池中成为空闲状态,等待执行下一个Runnable对象的run方法。

除此之外,使用线程池可以有效地控制系统中并发线程的数量,但系统中包含大量并发线程时,会导致系统性能剧烈下降,甚至导致JVM崩溃。而线程池的最大线程数参数可以控制系统中并发的线程不超过此数目。

在JDK1.5之前,开发者必须手动的实现自己的线程池,从JDK1.5之后,Java内建支持线程池。

与多线程并发的所有支持的类都在java.util.concurrent包中。我们可以使用里面的类更加的控制多线程的执行。

系统启动一个新线程的成本是比较高的,因为它涉及到与操作系统的交互。在这种情况下,使用线程池可以很好的提供性能,尤其是当程序中需要创建大量生存期很短暂的线程时,更应该考虑使用线程池

JDK1.5中提供Executors工厂类来产生连接池,该工厂类中包含如下的几个静态工程方法来创建连接池:

1、public static ExecutorService newFixedThreadPool(int nThreads):创建一个可重用的、具有固定线程数的线程池。

2、public static ExecutorService newSingleThreadExecutor():创建一个只有单线程的线程池,它相当于newFixedThreadPool方法是传入的参数为1

3、public static ExecutorService newCachedThreadPool():创建一个具有缓存功能的线程池,系统根据需要创建线程,这些线程将会被缓存在线程池中。

4、public static ScheduledExecutorService newSingleThreadScheduledExecutor:创建只有一条线程的线程池,他可以在指定延迟后执行线程任务

5、public static ScheduledExecutorService newScheduledThreadPool(int corePoolSize):创建具有指定线程数的线程池,它可以再指定延迟后执行线程任务,corePoolSize指池中所保存的线程数,即使线程是空闲的也被保存在线程池内。

上面的几个方法都有一个重载的方法,多传入一个ThreadFactory参数的重载方法,使用的比较少。

二、ExecutorService类

可以看到上面的5个方法中,前面3个方法的返回值都是一个ExecutorService对象。该ExecutorService对象就代表着一个尽快执行线程的线程池(只要线程池中有空闲线程立即执行线程任务),程序只要将一个Runnable对象或Callable对象提交给该线程池即可,该线程就会尽快的执行该任务。

ExecutorService有几个重要的方法:

更详细的参考JDK API文档。

submit方法是对 Executor接口execute方法的更好的封装,建议使用submit方法。

三、ScheduleExecutorService类

在上面的5个方法中,后面2个方法的返回值都是一个ScheduleExecutorService对象。ScheduleExecutorService代表可在指定延迟或周期性执行线程任务的线程池。

ScheduleExecutorService类是ExecutorService类的子类。所以,它里面也有直接提交任务的submit方法,并且新增了一些延迟任务处理的方法:

下面看看线程池的简单使用:

1、固定大小的线程池:

package com.bjpowernode.test; 
 import java.util.concurrent.ExecutorService; 
 import java.util.concurrent.Executors; 
 public class PoolTest { 
 public static void main(String[] args) { 
  ExecutorService pool=Executors.newFixedThreadPool(5);//创建一个固定大小为5的线程池 
  for(int i=0;i<7;i++){ 
  pool.submit(new MyThread()); 
  } 
  pool.shutdown(); 
 } 
 } 
 class MyThread extends Thread{ 
 @Override 
 public void run() { 
  System.out.println(Thread.currentThread().getName()+"正在执行。。。"); 
 } 
 } 

输出结果:

 pool-1-thread-1正在执行。。。 
 pool-1-thread-3正在执行。。。 
 pool-1-thread-2正在执行。。。 
 pool-1-thread-4正在执行。。。 
 pool-1-thread-4正在执行。。。 
 pool-1-thread-5正在执行。。。 
 pool-1-thread-1正在执行。。。 

可以看到虽然我们呢创建了7个MyThread线程对象,但是由于受线程池的大小限制,只是开启了5个线程,这样就减少了并发线程的数量。

2、单任务线程池:

 public class PoolTest { 
 public static void main(String[] args) { 
  ExecutorService pool=Executors.newSingleThreadExecutor();//创建一个单线程池 
  for(int i=0;i<7;i++){ 
  pool.submit(new MyThread()); 
  } 
  pool.shutdown(); 
 } 
 }

输出结果:

 pool-1-thread-1正在执行。。。 
 pool-1-thread-1正在执行。。。 
 pool-1-thread-1正在执行。。。 
 pool-1-thread-1正在执行。。。 
 pool-1-thread-1正在执行。。。 
 pool-1-thread-1正在执行。。。 
 pool-1-thread-1正在执行。。。 

可以看到,线程池只开启了一个线程。

3、创建可变尺寸的线程池

 public class PoolTest { 
 public static void main(String[] args) { 
  ExecutorService pool=Executors.newCachedThreadPool(); 
  for(int i=0;i<5;i++){ 
  pool.submit(new MyThread()); 
  } 
  pool.shutdown(); 
 } 
 } 

看输出结果:

 pool-1-thread-1正在执行。。。 
 pool-1-thread-3正在执行。。。 
 pool-1-thread-2正在执行。。。 
 pool-1-thread-4正在执行。。。 
 pool-1-thread-5正在执行。。。 

可以看到,我们没有限制线程池的大小,但是它会根据需求而创建线程。

4、延迟线程池

 public class PoolTest { 
 public static void main(String[] args) { 
  ScheduledExecutorService pool=Executors.newScheduledThreadPool(6); 
  for(int i=0;i<4;i++){ 
  pool.submit(new MyThread()); 
  } 
  
  pool.schedule(new MyThread(), 1000, TimeUnit.MILLISECONDS); 
  pool.schedule(new MyThread(), 1000, TimeUnit.MILLISECONDS); 
  pool.shutdown(); 
 } 
 } 

输出结果:

pool-1-thread-1正在执行。。。 
pool-1-thread-3正在执行。。。 
pool-1-thread-2正在执行。。。 
 pool-1-thread-4正在执行。。。 
 pool-1-thread-6正在执行。。。 
pool-1-thread-1正在执行。。。 

可以明显看到,最后两个线程不是立即执行,而是延迟了1秒在执行的。

5、单任务延迟线程池

 public class PoolTest { 
 public static void main(String[] args) { 
  ScheduledExecutorService pool=Executors.newSingleThreadScheduledExecutor(); 
  for(int i=0;i<4;i++){ 
  pool.submit(new MyThread()); 
  } 
  
  pool.schedule(new MyThread(), 1000, TimeUnit.MILLISECONDS); 
  pool.schedule(new MyThread(), 1000, TimeUnit.MILLISECONDS); 
  pool.shutdown(); 
 } 
 } 

上面我们使用的是JDK帮我封装好的线程池,我们也可以自己定义线程池,查看源码,我们发现,Excutors里面的获得线程的静态方法,内部都是调用ThreadPoolExecutor的构造方法。比如:

 public static ExecutorService newFixedThreadPool(int nThreads, ThreadFactory threadFactory) { 
 return new ThreadPoolExecutor(nThreads, nThreads, 
     0L, TimeUnit.MILLISECONDS, 
     new LinkedBlockingQueue<Runnable>(), 
     threadFactory); 
 } 

可以看到,它是通过调用ThreadPoolExecutor的构造方法来返回一个线程池的。所以,我们也可以自己手动的调用ThreadPoolExecutor的各种构造方法,来定义自己的线程池规则,不过一般情况下,使用自带的线程池就够了,不需要自己来实现。

以上所述是小编给大家介绍的Java 线程池,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对网站的支持!


# java  # 线程池  # Java 线程池ExecutorService详解及实例代码  # Java 线程池详解及实例代码  # Java Socket编程实例(三)- TCP服务端线程池  # Java线程池的几种实现方法及常见问题解答  # 四种Java线程池用法解析  # Java 线程池详解  # 可以看到  # 都是  # 创建一个  # 自己的  # 池中  # 的是  # 几个  # 就会  # 很好  # 尤其是  # 较高  # 因为它  # 连接池  # 涉及到  # 在这种情况下  # 方法来  # 很短  # 控制系统  # 小编  # 多线程 


相关栏目: 【 网站优化151355 】 【 网络推广146373 】 【 网络技术251813 】 【 AI营销90571


相关推荐: BootStrap整体框架之基础布局组件  Laravel如何操作JSON类型的数据库字段?(Eloquent示例)  Laravel如何实现多表关联模型定义_Laravel多对多关系及中间表数据存取【方法】  Laravel如何自定义错误页面(404, 500)?(代码示例)  如何在阿里云购买域名并搭建网站?  悟空识字如何进行跟读录音_悟空识字开启麦克风权限与录音  大连企业网站制作公司,大连2025企业社保缴费网上缴费流程?  如何快速搭建个人网站并优化SEO?  Win11怎么设置虚拟桌面 Win11新建多桌面切换操作【技巧】  jquery插件bootstrapValidator表单验证详解  零服务器AI建站解决方案:快速部署与云端平台低成本实践  高配服务器限时抢购:企业级配置与回收服务一站式优惠方案  php结合redis实现高并发下的抢购、秒杀功能的实例  nodejs redis 发布订阅机制封装实现方法及实例代码  如何用ChatGPT准备面试 模拟面试问答与职场话术练习教程  香港服务器部署网站为何提示未备案?  Laravel项目怎么部署到Linux_Laravel Nginx配置详解  Laravel怎么实现验证码功能_Laravel集成验证码库防止机器人注册  Laravel Seeder填充数据教程_Laravel模型工厂Factory使用  如何在景安云服务器上绑定域名并配置虚拟主机?  浏览器如何快速切换搜索引擎_在地址栏使用不同搜索引擎【搜索】  百度输入法ai面板怎么关 百度输入法ai面板隐藏技巧  Laravel如何实现用户密码重置功能?(完整流程代码)  VIVO手机上del键无效OnKeyListener不响应的原因及解决方法  Laravel怎么实现搜索高亮功能_Laravel结合Scout与Algolia全文检索【实战】  今日头条微视频如何找选题 今日头条微视频找选题技巧【指南】  手机网站制作平台,手机靓号代理商怎么制作属于自己的手机靓号网站?  如何自定义建站之星网站的导航菜单样式?  详解Android图表 MPAndroidChart折线图  Laravel怎么处理异常_Laravel自定义异常处理与错误页面教程  如何基于PHP生成高效IDC网络公司建站源码?  悟空浏览器如何设置小说背景色_悟空浏览器背景色设置【方法】  Laravel如何监控和管理失败的队列任务_Laravel失败任务处理与监控  Laravel如何使用Service Provider服务提供者_Laravel依赖注入与容器绑定【深度】  如何在HTML表单中获取用户输入并用JavaScript动态控制复利计算循环  Laravel Facade的原理是什么_深入理解Laravel门面及其工作机制  Laravel怎么做缓存_Laravel Cache系统提升应用速度的策略与技巧  Laravel任务队列怎么用_Laravel Queues异步处理任务提升应用性能  Laravel的Blade指令怎么自定义_创建你自己的Laravel Blade Directives  Android 常见的图片加载框架详细介绍  如何在宝塔面板创建新站点?  Laravel观察者模式如何使用_Laravel Model Observer配置  Python进程池调度策略_任务分发说明【指导】  如何破解联通资金短缺导致的基站建设难题?  如何将凡科建站内容保存为本地文件?  Laravel如何使用Blade模板引擎?(完整语法和示例)  北京的网站制作公司有哪些,哪个视频网站最好?  UC浏览器如何切换小说阅读源_UC浏览器阅读源切换【方法】  SQL查询语句优化的实用方法总结  python中快速进行多个字符替换的方法小结