码迷,mamicode.com
首页 > 编程语言 > 详细

线程池

时间:2019-10-18 18:55:11      阅读:86      评论:0      收藏:0      [点我收藏+]

标签:size   ram   read   最大   keepaliv   lib   中断   thread   link   

线程池参数

创建线程的api

ThreadPoolExecutor(int corePoolSize, int maximumPoolSize,
           long keepAliveTime, TimeUnit unit, BlockingQueue<Runnable> workQueue,
            RejectedExecutionHandler handler)

这几个核心参数的作用:
  • corePoolSize 为线程池的基本大小。
  • maximumPoolSize 为线程池最大线程大小。
  • keepAliveTime 和 unit 则是线程空闲后的存活时间。
  • workQueue 用于存放任务的阻塞队列。
  • handler 当队列和最大线程池都满了之后的饱和策略。

 

线程池定义的状态:

技术图片

 

 

 

  • RUNNING 自然是运行状态,指可以接受任务执行队列里的任务
  • SHUTDOWN 指调用了 shutdown() 方法,不再接受新任务了,但是队列里的任务得执行完毕。
  • STOP 指调用了 shutdownNow() 方法,不再接受新任务,同时抛弃阻塞队列里的所有任务并中断所有正在执行任务。
  • TIDYING 所有任务都执行完毕,在调用 shutdown()/shutdownNow() 中都会尝试更新为这个状态。
  • TERMINATED 终止状态,当执行 terminated() 后会更新为这个状态。

 

通常我们都是用:  threadPool.execute(new Job())的方式来提交一个任务到线程池中,核心就是execute()函数,其过程是:

  1. 获取当前线程池的状态。
  2. 当前线程数量小于 coreSize 时创建一个新的线程运行。
  3. 如果当前线程处于运行状态,并且写入阻塞队列成功。
  4. 双重检查,再次获取线程池状态;如果线程池状态变了(非运行状态)就需要从阻塞队列移除任务,并尝试判断线程是否全部执行完毕。同时执行拒绝策略。
  5. 如果当前线程池为空就新创建一个线程并执行。
  6. 如果在第三步的判断为非运行状态,尝试新建线程,如果失败则执行拒绝策略

借助<聊聊并发>的一张图来描述这个过程:

技术图片

 

 

 

SpringBoot使用线程池:

配置参数

@Configuration
@EnableAsync
public class ThreadPoolConfig {

  @Bean("threadPool")
  public Executor taskExecutor() {
    ThreadPoolTaskExecutor taskExecutor=new ThreadPoolTaskExecutor();
    taskExecutor.setCorePoolSize(10);//线程池最小线程数
    taskExecutor.setMaxPoolSize(50);//线程池最大线程数
    taskExecutor.setQueueCapacity(200);//阻塞对量大小
    taskExecutor.setKeepAliveSeconds(60);//线程空闲时间
    taskExecutor.setThreadNamePrefix("taskThread--");//线程名称前缀
    taskExecutor.setWaitForTasksToCompleteOnShutdown(true);//关闭线程时是否等待完成任务
    taskExecutor.setAwaitTerminationSeconds(60);//等待进入终止状态时间
    taskExecutor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy());//线程池饱 和拒绝任务策略
    return taskExecutor;
  }

}

测试使用线程池:

@Component
public class TestService {

  @Async("threadPool")
  public void test() {
  System.out.println("名字:"+Thread.currentThread().getName());
  }
}

 

线程池隔离

根据业务将线程池进行隔离,单独的业务系统使用单独的线程池,通过hystrix来实现

添加hystrix依赖

<dependency>
  <groupId>org.springframework.cloud</groupId>
  <artifactId>spring-cloud-starter-netflix-hystrix</artifactId>
  <version>2.1.3.RELEASE</version>
</dependency>

定义两个线程池,分别处理订单,用户任务

public class OrderCommand extends HystrixCommand<String> {

  private String orderName;

  private static final Logger LOG=LoggerFactory.getLogger(OrderCommand.class);

  public OrderCommand(String orderName) {
    super(Setter.withGroupKey(
    //服务分组
    HystrixCommandGroupKey.Factory.asKey("OrderGroup"))
    //线程分组
    .andThreadPoolKey(HystrixThreadPoolKey.Factory.asKey("OrderPool"))
    //线程池配置
    .andThreadPoolPropertiesDefaults(HystrixThreadPoolProperties.Setter()
    .withCoreSize(8)
    .withMaximumSize(16)
    .withKeepAliveTimeMinutes(6000)
    .withMaxQueueSize(50)
    .withQueueSizeRejectionThreshold(1000))
    //线程池隔离
    .andCommandPropertiesDefaults(HystrixCommandProperties.Setter().withExecutionIsolationStrategy(E    xecutionIsolationStrategy.THREAD)));
    this.orderName=orderName;
  }

  @Override
  protected String run() throws Exception {
    LOG.info("orderName=[{}]",orderName);
    return "orderName:"+orderName;
  }
}

UserCommand

 

public class UserCommand extends HystrixCommand<String> {

  private String userName;
  private static final Logger LOG=LoggerFactory.getLogger(UserCommand.class);

  public UserCommand(String userName) {
    super(Setter.withGroupKey(
    //服务分组
    HystrixCommandGroupKey.Factory.asKey("UserGroup"))
    //线程分组
    .andThreadPoolKey(HystrixThreadPoolKey.Factory.asKey("UserPool"))
    //线程池配置
    .andThreadPoolPropertiesDefaults(HystrixThreadPoolProperties.Setter()
    .withCoreSize(8)
    .withMaximumSize(16)
    .withKeepAliveTimeMinutes(6000)
    .withMaxQueueSize(50)
    .withQueueSizeRejectionThreshold(1000))
    //线程池隔离
    .andCommandPropertiesDefaults(HystrixCommandProperties.Setter().withExecutionIsolationStrategy(E    xecutionIsolationStrategy.THREAD)));
    this.userName=userName;
  }

@Override
protected String run() throws Exception {
  LOG.info("userName=[{}]", userName);
  TimeUnit.MILLISECONDS.sleep(300);
  return "userName:"+userName;
}
}

 

测试

OrderCommand o1 = new OrderCommand("手机");
OrderCommand o2 = new OrderCommand("电脑");
UserCommand o3 = new UserCommand("张三");
//阻塞方式
String r1 = o1.execute();
String r2 = o2.execute();
String r3 = o3.execute();
//异常非阻塞
// Future<String> f = o3.queue();
// try {
// String r3 = f.get(300,TimeUnit.MILLISECONDS);
// System.out.println(r3);
// } catch (InterruptedException | ExecutionException | TimeoutException e) {
// e.printStackTrace();
// }

结果:

技术图片

 

 

 

 

 

 

 

 

 

 

线程池

标签:size   ram   read   最大   keepaliv   lib   中断   thread   link   

原文地址:https://www.cnblogs.com/nanbcdx/p/11699794.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!