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

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

线程池

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

与数据库连接池类似的是,线程池在系统启动时即创建大量空闲的线程,程序将一个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有几个重要的方法:

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

更详细的参考JDK API文档。

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

三、ScheduleExecutorService类

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

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

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

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

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 线程池,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对网站的支持!


> 本站内容系网友提交或本网编辑转载,其目的在于传递更多信息,并不代表本网赞同其观点和对其真实性负责。如涉及作品内容、版权和其它问题,请及时与本网联系,我们将在第一时间删除内容!

相关文章
  • 将xml文件作为一个小的数据库,进行学生的增删改查的简单实例
    下面小编就为大家带来一篇将xml文件作为一个小的数据库,进行学生的增删改查的简单实例.小编觉得挺不错的,现在就分享给大家,也给大家做个参考.一起跟随小编过来看看吧1.xml文件: <?xml version="1.0" encoding="UTF-8"?><Students> <stude ...
  • 正则表达式性能优化方法高效正则表达式书写
    正则表达式性能优化方法高效正则表达式书写
    这里说的正则表达式优化,主要是针对目前常用的NFA模式正则表达式这里说的正则表达式优化,主要是针对目前常用的NFA模式正则表达式,详细可以参考:正则表达式匹配解析过程探讨分析(正则表达式匹配原理).从上面例子,我们可以推断出,影响NFA类正则表达式(常见语言:GNU Emacs,Java,ergp,less,more,.NET语言, PCRE library ...
  • php项目开发中用到的快速排序算法分析
    这篇文章主要介绍了php项目开发中用到的快速排序算法,结合实例形式详细分析了php快速排序的原理与使用方法,需要的朋友可以参考下本文实例讲述了php项目开发中用到的快速排序算法.分享给大家供大家参考,具体如下: 实际上在,做web开发,比较少遇到使用一些算法之类的,毕竟不是做搜索引擎,也不是写底层(比如写个类似于mysql这样的数据库,里面需要自己实现排序算 ...
  • JavaWeb实现图形报表折线图的方法
    这篇文章主要介绍了JavaWeb实现图形报表折线图的方法,涉及JSP包的引用.图形操作.配置文件设置及字符串操作技巧,需要的朋友可以参考下本文实例讲述了JavaWeb实现图形报表折线图的方法.分享给大家供大家参考,具体如下: 步骤说明: 1. 导入log4j.jar,jfreechart-0.9.18.jar,jdom.jar,jcommon-0.9.3.j ...
  • Web2.0编程思想:16条法则
    1.在你开始之前,先定一个简单的目标.无论你是一个Web 2.0应用的创建者还是用户,请清晰的构思你的目标.就像"我需要保存一个书签"或者"我准备帮助人们创建可编辑的.共享的页面"这样的目标,让你保持最基础的需求.很多Web 2.0应用的最初吸引之处就是它的简单,避免并隐藏了那些多余的复杂性.站在创建者的立场,可以想象 ...
  • 提高代码可读性的十大注释技巧分享
    这篇文章主要介绍了提高代码可读性的十大注释技巧,详细分析了编程开发中常用的代码注释方法,需要的朋友可以参考下本文讲述了提高代码可读性的十大注释技巧.分享给大家供大家参考,具体如下: 很多程序员在写代码的时候往往都不注意代码的可读性,让别人在阅读代码时花费更多的时间.其实,只要程序员在写代码的时候,注意为代码加注释,并以合理的格式为代码加注释,这样就方便别人查 ...
猜你喜欢