加入收藏 | 设为首页 | 会员中心 | 我要投稿 湖南网 (https://www.hunanwang.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 建站 > 正文

关于线程池你不能不知道的东西

发布时间:2019-07-08 16:24:08 所属栏目:建站 来源:儒雅程序员
导读:媒介 平常打仗过多线程开拓的童鞋应该都或多或少相识过线程池,之前宣布的《阿里巴巴 Java 手册》里也有一条: 可见线程池的重要性。 简朴来说行使线程池有以下几个目标: 线程是稀缺资源,不能频仍的建设。 解耦浸染;线程建设于执行完全分隔,利便维护 应

我凡是是凭证以下方法封锁线程池的:

  1. long start = System.currentTimeMillis(); 
  2.  for (int i = 0; i <= 5; i++) { 
  3.  pool.execute(new Job()); 
  4.  } 
  5.  pool.shutdown(); 
  6.  while (!pool.awaitTermination(1, TimeUnit.SECONDS)) { 
  7.  LOGGER.info("线程还在执行。。。"); 
  8.  } 
  9.  long end = System.currentTimeMillis(); 
  10.  LOGGER.info("一共处理赏罚了【{}】", (end - start)); 

pool.awaitTermination(1, TimeUnit.SECONDS) 会每隔一秒钟搜查一次是否执行完毕(状态为 TERMINATED),当从 while 轮回退出时就表白线程池已经完全终止了。

SpringBoot 行使线程池

2018 年了,SpringBoot 流行;来看看在 SpringBoot 中该当怎么设置和行使线程池。

既然用了 SpringBoot ,那天然得施展 Spring 的特征,以是必要 Spring 来帮我们打点线程池:

  1. @Configuration 
  2. public class TreadPoolConfig { 
  3.  /** 
  4.  * 斲丧行列线程 
  5.  * @return 
  6.  */ 
  7.  @Bean(value = "consumerQueueThreadPool") 
  8.  public ExecutorService buildConsumerQueueThreadPool(){ 
  9.  ThreadFactory namedThreadFactory = new ThreadFactoryBuilder() 
  10.  .setNameFormat("consumer-queue-thread-%d").build(); 
  11.  ExecutorService pool = new ThreadPoolExecutor(5, 5, 0L, TimeUnit.MILLISECONDS, 
  12.  new ArrayBlockingQueue(5),namedThreadFactory,new ThreadPoolExecutor.AbortPolicy()); 
  13.  return pool ; 
  14.  } 

行使时:

  1. @Resource(name = "consumerQueueThreadPool") 
  2.  private ExecutorService consumerQueueThreadPool; 
  3.  @Override 
  4.  public void execute() { 
  5.  //斲丧行列 
  6.  for (int i = 0; i < 5; i++) { 
  7.  consumerQueueThreadPool.execute(new ConsumerQueueThread()); 
  8.  } 
  9.  } 

着实也挺简朴,就是建设了一个线程池的 bean,在行使时直接从 Spring 中取出即可。

监控线程池

谈到了 SpringBoot,也可操作它 actuator 组件来做线程池的监控。

线程怎么说都是稀缺资源,对线程池的监控可以知道本身使命执行的状况、服从等。

关于 actuator 就不再细说了,感乐趣的可以看看这篇,有具体清算过怎样袒露监控端点。

着实 ThreadPool 自己已经提供了不少 api 可以获取线程状态:

干货:关于线程池你不能不知道的对象

许多要领看名字就知道其寄义,只必要将这些信息袒露到 SpringBoot 的监控端点中,我们就可以在可视化页面查察当前的线程池状态了。

乃至我们可以担任线程池扩展个中的几个函数来自界说监控逻辑:

干货:关于线程池你不能不知道的对象

干货:关于线程池你不能不知道的对象

看这些名称和界说都知道,这是让子类来实现的。

可以在线程执行前、后、终止状态执行自界说逻辑。

线程池断绝

线程池看似很柔美,但也会带来一些题目。

假如我们许多营业都依靠于统一个线程池,当个中一个营业由于各类不行控的缘故起因耗损了全部的线程,导致线程池所有占满。

这样其他的营业也就不能正常运转了,这对体系的冲击是庞大的。

好比我们 Tomcat 接管哀求的线程池,假设个中一些相应出格慢,线程资源得不到接纳开释;线程池逐步被占满,最坏的环境就是整个应用都不能提供处事。

以是我们必要将线程池举办断绝。

凡是的做法是凭证营业举办分别:

好比下单的使命用一个线程池,获取数据的使命用另一个线程池。这样纵然个中一个呈现题目把线程池耗尽,那也不会影响其他的使命运行。

hystrix 断绝

这样的需求 Hystrix 已经帮我们实现了。

Hystrix 是一款开源的容错插件,具有依靠断绝、体系容错降级等成果。

下面来看看 Hystrix 简朴的应用:

起首必要界说两个线程池,别离用于执行订单、处理赏罚用户。

  1. /** 
  2.  * Function:订单处事 
  3.  * 
  4.  * @author crossoverJie 
  5.  * Date: 2018/7/28 16:43 
  6.  * @since JDK 1.8 
  7.  */ 
  8. public class CommandOrder extends HystrixCommand<String> { 
  9.  private final static Logger LOGGER = LoggerFactory.getLogger(CommandOrder.class); 
  10.  private String orderName; 
  11.  public CommandOrder(String orderName) { 
  12.  super(Setter.withGroupKey( 
  13.  //处事分组 
  14.  HystrixCommandGroupKey.Factory.asKey("OrderGroup")) 
  15.  //线程分组 
  16.  .andThreadPoolKey(HystrixThreadPoolKey.Factory.asKey("OrderPool")) 
  17.  //线程池设置 
  18.  .andThreadPoolPropertiesDefaults(HystrixThreadPoolProperties.Setter() 
  19.  .withCoreSize(10) 
  20.  .withKeepAliveTimeMinutes(5) 
  21.  .withMaxQueueSize(10) 
  22.  .withQueueSizeRejectionThreshold(10000)) 
  23.  .andCommandPropertiesDefaults( 
  24.  HystrixCommandProperties.Setter() 
  25.  .withExecutionIsolationStrategy(HystrixCommandProperties.ExecutionIsolationStrategy.THREAD)) 
  26.  ) 
  27.  ; 
  28.  this.orderName = orderName; 
  29.  } 
  30.  @Override 
  31.  public String run() throws Exception { 
  32.  LOGGER.info("orderName=[{}]", orderName); 
  33.  TimeUnit.MILLISECONDS.sleep(100); 
  34.  return "OrderName=" + orderName; 
  35.  } 
  36. /** 
  37.  * Function:用户处事 
  38.  * 
  39.  * @author crossoverJie 
  40.  * Date: 2018/7/28 16:43 
  41.  * @since JDK 1.8 
  42.  */ 
  43. public class CommandUser extends HystrixCommand<String> { 
  44.  private final static Logger LOGGER = LoggerFactory.getLogger(CommandUser.class); 
  45.  private String userName; 
  46.  public CommandUser(String userName) { 
  47.  super(Setter.withGroupKey( 
  48.  //处事分组 
  49.  HystrixCommandGroupKey.Factory.asKey("UserGroup")) 
  50.  //线程分组 
  51.  .andThreadPoolKey(HystrixThreadPoolKey.Factory.asKey("UserPool")) 
  52.  //线程池设置 
  53.  .andThreadPoolPropertiesDefaults(HystrixThreadPoolProperties.Setter() 
  54.  .withCoreSize(10) 
  55.  .withKeepAliveTimeMinutes(5) 
  56.  .withMaxQueueSize(10) 
  57.  .withQueueSizeRejectionThreshold(10000)) 
  58.  //线程池断绝 
  59.  .andCommandPropertiesDefaults( 
  60.  HystrixCommandProperties.Setter() 
  61.  .withExecutionIsolationStrategy(HystrixCommandProperties.ExecutionIsolationStrategy.THREAD)) 
  62.  ) 
  63.  ; 
  64.  this.userName = userName; 
  65.  } 
  66.  @Override 
  67.  public String run() throws Exception { 
  68.  LOGGER.info("userName=[{}]", userName); 
  69.  TimeUnit.MILLISECONDS.sleep(100); 
  70.  return "userName=" + userName; 
  71.  } 

api 出格简捷易懂,详细详情请查察官方文档。

(编辑:湖南网)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

热点阅读