java 注解实现一个可配置线程池的方法示例

前言

项目需要多线程执行一些Task,为了方便各个服务的使用。特意封装了一个公共工具类,下面直接撸代码:

PoolConfig(线程池核心配置参数):

/**
 * <h1>线程池核心配置(<b style="color:#CD0000">基本线程池数量、最大线程池数量、队列初始容量、线程连接保持活动秒数(默认60s)</b>)</h1>
 *
 * <blockquote><code>
 * <table border="1px" style="border-color:gray;" width="100%"><tbody>
 * <tr><th style="color:green;text-align:left;">
 * 属性名称
 * </th><th style="color:green;text-align:left;">
 * 属性含义
 * </th></tr>
 * <tr><td>
 * queueCapacity
 * </td><td>
 * 基本线程池数量
 * </td></tr>
 * <tr><td>
 * count
 * </td><td>
 * 最大线程池数量
 * </td></tr>
 * <tr><td>
 * maxCount
 * </td><td>
 * 队列初始容量
 * </td></tr>
 * <tr><td>
 * aliveSec
 * </td><td>
 * 线程连接保持活动秒数(默认60s)
 * </td></tr>
 * </tbody></table>
 * </code></blockquote>

 */
public class PoolConfig {

 private int queueCapacity = 200;

 private int count = 0;

 private int maxCount = 0;

 private int aliveSec;

 public int getQueueCapacity() {
 return queueCapacity;
 } 

 public void setQueueCapacity(int queueCapacity) {
 this.queueCapacity = queueCapacity;
 }

 public void setCount(int count) {
 this.count = count;
 }

 public void setMaxCount(int maxCount) {
 this.maxCount = maxCount;
 }

 public void setAliveSec(int aliveSec) {
 this.aliveSec = aliveSec;
 }

 public int getCount() {
 return count;
 }

 public int getMaxCount() {
 return maxCount;
 }

 public int getAliveSec() {
 return aliveSec;
 }
}

ThreadPoolConfig(线程池配置 yml配置项以thread开头):

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;

/**
 * <h1>线程池配置(<b style="color:#CD0000">线程池核心配置、各个业务处理的任务数量</b>)</h1>
 *
 * <blockquote><code>
 * <table border="1px" style="border-color:gray;" width="100%"><tbody>
 * <tr><th style="color:green;text-align:left;">
 * 属性名称
 * </th><th style="color:green;text-align:left;">
 * 属性含义
 * </th></tr>
 * <tr><td>
 * pool
 * </td><td>
 * 线程池核心配置
 * 【{@link PoolConfig}】
 * </td></tr>
 * <tr><td>
 * count
 * </td><td>
 * 线程池各个业务任务初始的任务数
 * </td></tr>
 * </tbody></table>
 * </code></blockquote>

 */
@Component
@ConfigurationProperties(prefix="thread")
public class ThreadPoolConfig {

 private PoolConfig pool = new PoolConfig();

 Map<String, Integer> count = new HashMap<>();

 public PoolConfig getPool() {
 return pool;
 }

 public void setPool(PoolConfig pool) {
 this.pool = pool;
 }

 public Map<String, Integer> getCount() {
 return count;
 }

}

定义Task注解,方便使用:

@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Component
public @interface ExcutorTask {

 /**
 * The value may indicate a suggestion for a logical ExcutorTask name,
 * to be turned into a Spring bean in case of an autodetected ExcutorTask .
 * @return the suggested ExcutorTask name, if any
 */
 String value() default "";

}

通过反射获取使用Task注解的任务集合:

public class Beans {

 private static final char PREFIX = '.';

 public static ConcurrentMap<String, String> scanBeanClassNames(){
 ConcurrentMap<String, String> beanClassNames = new ConcurrentHashMap<>();
 ClassPathScanningCandidateComponentProvider provider = new ClassPathScanningCandidateComponentProvider(false);
   provider.addIncludeFilter(new AnnotationTypeFilter(ExcutorTask.class));
   for(Package pkg : Package.getPackages()){
   String basePackage = pkg.getName();
     Set<BeanDefinition> components = provider.findCandidateComponents(basePackage);
     for (BeanDefinition component : components) {
     String beanClassName = component.getBeanClassName();
     try {
    Class<?> clazz = Class.forName(component.getBeanClassName());
    boolean isAnnotationPresent = clazz.isAnnotationPresent(ZimaTask.class);
    if(isAnnotationPresent){
     ZimaTask task = clazz.getAnnotation(ExcutorTask.class);
     String aliasName = task.value();
     if(aliasName != null && !"".equals(aliasName)){
     beanClassNames.put(aliasName, component.getBeanClassName());
     }
    }
    } catch (ClassNotFoundException e) {
    e.printStackTrace();
    }
     beanClassNames.put(beanClassName.substring(beanClassName.lastIndexOf(PREFIX) + 1), component.getBeanClassName());
     }
   }
   return beanClassNames;
  }
}

线程执行类TaskPool:

@Component
public class TaskPool {

 public ThreadPoolTaskExecutor poolTaskExecutor;

 @Autowired
 private ThreadPoolConfig threadPoolConfig;

 @Autowired
 private ApplicationContext context;

 private final Integer MAX_POOL_SIZE = 2000;

 private PoolConfig poolCfg;

 private Map<String, Integer> tasksCount;

 private ConcurrentMap<String, String> beanClassNames;

 @PostConstruct
  public void init() {

 beanClassNames = Beans.scanBeanClassNames();

   poolTaskExecutor = new ThreadPoolTaskExecutor();

   poolCfg = threadPoolConfig.getPool();

 tasksCount = threadPoolConfig.getCount();

 int corePoolSize = poolCfg.getCount(),
  maxPoolSize = poolCfg.getMaxCount(),
  queueCapacity = poolCfg.getQueueCapacity(),
  minPoolSize = 0, maxCount = (corePoolSize << 1);

 for(String taskName : tasksCount.keySet()){
  minPoolSize += tasksCount.get(taskName);
 }

 if(corePoolSize > 0){
  if(corePoolSize <= minPoolSize){
  corePoolSize = minPoolSize;
  }
 }else{
  corePoolSize = minPoolSize;
 }

 if(queueCapacity > 0){
  poolTaskExecutor.setQueueCapacity(queueCapacity);
 }

 if(corePoolSize > 0){
  if(MAX_POOL_SIZE < corePoolSize){
  corePoolSize = MAX_POOL_SIZE;
  }
  poolTaskExecutor.setCorePoolSize(corePoolSize);
 }

 if(maxPoolSize > 0){
  if(maxPoolSize <= maxCount){
  maxPoolSize = maxCount;
  }
  if(MAX_POOL_SIZE < maxPoolSize){
  maxPoolSize = MAX_POOL_SIZE;
  }
  poolTaskExecutor.setMaxPoolSize(maxPoolSize);
 }

 if(poolCfg.getAliveSec() > 0){
  poolTaskExecutor.setKeepAliveSeconds(poolCfg.getAliveSec());
 }

 poolTaskExecutor.initialize();
  }

 public void execute(Class<?>... clazz){
 int i = 0, len = tasksCount.size();
 for(; i < len; i++){
  Integer taskCount = tasksCount.get(i);
  for(int t = 0; t < taskCount; t++){
  try{
   Object taskObj = context.getBean(clazz[i]);
   if(taskObj != null){
   poolTaskExecutor.execute((Runnable) taskObj);
   }
  }catch(Exception ex){
   ex.printStackTrace();
  }
  }
 }
  }

 public void execute(String... args){
   int i = 0, len = tasksCount.size();
 for(; i < len; i++){
  Integer taskCount = tasksCount.get(i);
  for(int t = 0; t < taskCount; t++){
  try{
   Object taskObj = null;
   if(context.containsBean(args[i])){
   taskObj = context.getBean(args[i]);
   }else{
   if(beanClassNames.containsKey(args[i].toLowerCase())){
    Class<?> clazz = Class.forName(beanClassNames.get(args[i].toLowerCase()));
    taskObj = context.getBean(clazz);
   }
   }
   if(taskObj != null){
   poolTaskExecutor.execute((Runnable) taskObj);
   }
  }catch(Exception ex){
   ex.printStackTrace();
  }
  }
 }
  }

 public void execute(){
 for(String taskName : tasksCount.keySet()){
  Integer taskCount = tasksCount.get(taskName);
  for(int t = 0; t < taskCount; t++){
  try{
   Object taskObj = null;
   if(context.containsBean(taskName)){
   taskObj = context.getBean(taskName);
   }else{
   if(beanClassNames.containsKey(taskName)){
    Class<?> clazz = Class.forName(beanClassNames.get(taskName));
    taskObj = context.getBean(clazz);
   }
   }
   if(taskObj != null){
   poolTaskExecutor.execute((Runnable) taskObj);
   }
  }catch(Exception ex){
   ex.printStackTrace();
  }
  }
 }
  }

}

如何使用?(做事就要做全套 ^_^)

1.因为使用的springboot项目,需要在application.properties 或者 application.yml 添加

#配置执行的task线程数
thread.count.NeedExcutorTask=4
#最大存活时间
thread.pool.aliveSec=300000
#其他配置同理

2.将我们写的线程配置进行装载到我们的项目中

@Configuration
public class TaskManager {

 @Resource
 private TaskPool taskPool;

 @PostConstruct
 public void executor(){
 taskPool.execute();
 }
}

3.具体使用

@ExcutorTask
public class NeedExcutorTask implements Runnable{
  @Override
 public void run() {
    Thread.sleep(1000L);
    log.info("====== 任务执行 =====")
  }
}

以上就是创建一个可扩展的线程池相关的配置(望指教~~~)。希望对大家的学习有所帮助,也希望大家多多支持我们。

(0)

相关推荐

  • 浅谈Java自定义注解和运行时靠反射获取注解

    java自定义注解 Java注解是附加在代码中的一些元信息,用于一些工具在编译.运行时进行解析和使用,起到说明.配置的功能. 注解不会也不能影响代码的实际逻辑,仅仅起到辅助性的作用.包含在 java.lang.annotation 包中. 1.元注解 元注解是指注解的注解.包括  @Retention @Target @Document @Inherited四种. 1.1.@Retention: 定义注解的保留策略 @Retention(RetentionPolicy.SOURCE) //注解仅

  • windows下zookeeper配置java环境变量的方法

    先找到文件 zookeeper的bin目录下编辑zkEnv.cmd 修改如下图 如果你的系统有多个JAVA_HOME类型的系统变量  则需要在该文件中指定用哪一个,并且还要修改windows的jdk环境变量 总结 以上就是这篇文章的全部内容了,希望本文的内容对大家的学习或者工作具有一定的参考学习价值,谢谢大家对我们的支持.如果你想了解更多相关内容请查看下面相关链接

  • Java反射机制的精髓讲解

    1,什么是反射? java的反射,允许程序在运行时,创建一个对象,获取一个类的所有相关信息等. 2,Class类 要了解反射,就绕不开Class类. 我们平时开发的类,例如ClassA,一般会有一些属性,会有几个构造方法,也会有一些普通方法,我们还可以使用ClassA来创建对象,例如ClassA classA = new ClassA(). java程序在运行时,其实是很多类的很多个对象之间的协作.jvm如何管理这些类呢?它如何知道各个类的名称,每个类都有哪些属性和哪些方法呢? jvm会给每个类

  • Java利用反射如何查找使用指定注解的类详解

    前言 最近有些空,想自己写个跟spring里的注解一样的注解来用,然后希望能找到使用了自己写了注解的类,下面来介绍一下实现方法 声明,下面代码是没看过spring源码写的,基本上都是网上找的博客,整理的 定义注解 Controller.java @Target({ElementType.TYPE}) @Retention(RetentionPolicy.RUNTIME) @Documented public @interface Controller { } RequestMapping.jav

  • 使用java的注解(用在java类的方法上的注解)方法

    场景:根据方法上的注解,通过java反射方式找到需要执行的的方法. 1.注解类 /**注解作用在方法上*/ @Target({ElementType.METHOD}) /**注解的生命周期一直程序运行时都存在VM运行期间保留注解,可以通过反射机制读取注解信息*/ @Retention(RetentionPolicy.RUNTIME) /**注解包含在Javadoc中*/ @Documented public @interface Item { String value(); } 2.在类的方法上

  • java 注解annotation的使用以及反射如何获取注解

     一.注解基本知识 1.元注解 元注解是指注解的注解.包括  @Retention @Target @Document @Inherited四种. 1. Annotation型定义为@interface, 所有的Annotation会自动继承java.lang.Annotation这一接口,并且不能再去继承别的类或是接口. 2. 参数成员只能用public或默认(default)这两个访问权修饰 3. 参数成员只能用基本类型byte,short,char,int,long,float,doubl

  • 浅谈Java中replace与replaceAll区别

    看门见山 1.java中replace API: replace(char oldChar, char newChar):寓意为:返回一个新的字符串,它是通过用 newChar 替换此字符串中出现的所有 oldChar 得到的. replace(CharSequence target, CharSequence replacement):寓意为:使用指定的字面值替换序列替换此字符串所有匹配字面值目标序列的子字符串. replaceAll(String regex, String replacem

  • 实例讲解Java基础之反射

    前期准备 编写一个真实类phone,实现list接口 public class Phone implements List { public double price; public String name; public Phone() { } public Phone(double price, String name) { this.price = price; this.name = name; } public double getPrice() { return price; } p

  • Java注解与反射原理说明

    一 点睛 注解若想发挥更大作用,还需借助反射机制之力.通过反射,可以取得一个方法上声明的注解的全部内容. 一般有两种需求: 1 取得方法中全部的注解,通过调用getAnnotations来实现. 2 判断操作是否是指定注解,通过调用getAnnotation来实现. 下面从源码角度来说明怎样获取这些注解信息. 二 源码导读--取得方法中全部的注解 public class AccessibleObject implements AnnotatedElement { ... //取得全部Annot

  • 深入理解Java高级特性——注解

    博主在初学注解的时候看到网上的介绍大部分都是直接介绍用法或者功能,没有实际的应用场景,篇幅又很长导致学习的时候难以理解其意图,而且学完就忘QAQ.本篇文章中我将结合实际的应用场景尽可能由浅入深,平缓的介绍java注解. java注解是jdk1.5以后新出的特性,对于它的应用非常广泛,我们首先来看一下注解的应用,百度百科上这样说: 我们可以看到,注解的作用有三方面: 编写doc文档:这个就我们很常用的 @return 以及 @author,加了这些注解以后,就可以用jdk帮我们自动生成对应的API

随机推荐