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

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

线程池

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

与数据库连接池类似的是,线程池在系统启动时即创建大量空闲的线程,程序将一个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中Context的详细介绍和实例分析

    JAVA中Context的详细介绍和实例分析

    这篇文章主要介绍了JAVA中Context的详细介绍和实例分析,Context是维持android各组件能够正常工作的一个核心功能类。如果感兴趣来学习一下
    2020-07-07
  • java中jvm逃逸问题分析

    java中jvm逃逸问题分析

    本篇文章给大家详细总结了java中jvm逃逸问题的相关内容,有兴趣的朋友可以根据小编一起学习下。
    2018-02-02
  • Spring注解之@validated使用详解

    Spring注解之@validated使用详解

    spring-boot中可以用@validated来校验数据,如果数据异常则会统一抛出异常,方便异常中心统一处理,这篇文章主要介绍了Spring注解之@validated使用,需要的朋友可以参考下
    2023-01-01
  • Java ArrayList与LinkedList使用方法详解

    Java ArrayList与LinkedList使用方法详解

    Java中容器对象主要用来存储其他对象,根据实现原理不同,主要有3类常用的容器对象:ArrayList使用数组结构存储容器中的元素、LinkedList使用链表结构存储容器中的元素
    2022-11-11
  • java实现解析json复杂数据的方法详解

    java实现解析json复杂数据的方法详解

    这篇文章主要为大家详细介绍了java如何实现解析json复杂数据,文中的示例代码讲解详细,具有一定的借鉴价值,感兴趣的小伙伴可以学习一下
    2024-01-01
  • Java中Math类常用方法代码详解

    Java中Math类常用方法代码详解

    本文是小编最新给大家整理的关于Java中Math类常用方法的知识,通过实例代码给大家介绍的非常详细,感兴趣的朋友一起看看吧
    2017-07-07
  • 全面理解Java类和对象

    全面理解Java类和对象

    下面小编就为大家带来一篇全面理解Java类和对象。小编觉得挺不错的,现在就分享给大家,也给大家做个参考。一起跟随小编过来看看吧
    2016-06-06
  • 基于TCP通信丢包原因总结(推荐)

    基于TCP通信丢包原因总结(推荐)

    下面小编就为大家带来一篇基于TCP通信丢包原因总结(推荐)。小编觉得挺不错的,现在就分享给大家,也给大家做个参考。一起跟随小编过来看看吧
    2017-08-08
  • Java中的类加载与类卸载方式

    Java中的类加载与类卸载方式

    这篇文章主要介绍了Java中的类加载与类卸载方式,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教
    2023-12-12
  • Java并发编程之Fork/Join框架的理解

    Java并发编程之Fork/Join框架的理解

    今天带大家学习Java并发编程的相关知识,文中对Fork/Join框架作了非常详细的介绍,对正在学习有关知识的小伙伴们很有帮助,需要的朋友可以参考下
    2021-06-06

最新评论