首先接口函数的定义:使用策略模式,不同的接口实现类统一实现一个被实现的接口类
public interface ThreadServiceBase {
/**
*
* 用来被继承使用
*/
}
然后不同的接口实现类都实现这个接口,每个实现类有自己的定义业务接口,例如
接口定义好后,定义枚举类,枚举类有两种模式,
THREADTHREE("threadThree",new ThreadThreeServiceImpl()),
THREADONE("threadOne",new ThreadServiceImpl());
or
THREADTHREE("threadThree", "ThreadThreeServiceImpl"),
THREADONE("threadOne", "ThreadServiceImpl");
l分别对应的线程的处理方式如下:
// 这里使用的是枚举类中new对象后直接调用的方式
public class ThreadPoolInterfaceInvoke implements Callable<Pair<Integer, Integer>> {
private static final Logger logger = LoggerFactory.getLogger(ThreadPoolInterfaceInvoke.class);
/*开发思路:一个线程只能调用一次,外部使用线程池过来调用,所以这里需要配备四个接口的调用参数。
* 用到了 线程 参数传递 枚举 反射*/
private String v;
/**
*
*/
private Pair<Integer, Integer> pairThreadLocal;
public ThreadPoolInterfaceInvoke(){}
public ThreadPoolInterfaceInvoke(String v){
this.v = v;
}
@Override
public Pair<Integer, Integer> call() throws Exception {
ThreadService threadService = (ThreadService)ThreadEnum.get(v).getServiceClass();
int threadOne = threadService.threadOne();
logger.info("threadOne name v:{}, threadOne value:{}",v,threadOne);
int threadTwo = threadService.threadTwo();
logger.info("threadTwo name v:{}, threadTwo value:{}",v,threadTwo);
pairThreadLocal = new Pair<Integer, Integer>(threadOne,threadTwo);
return pairThreadLocal;
}
}
// 这种方式是通过,反射原理从spring工厂获取bean在调用方法
public class ThreadPoolInterfaceInvokeTwo implements Callable<Pair<Integer, Integer>> {
private static final Logger logger = LoggerFactory.getLogger(ThreadPoolInterfaceInvokeTwo.class);
/*开发思路:一个线程只能调用一次,外部使用线程池过来调用,所以这里需要配备四个接口的调用参数。
* 用到了 线程 参数传递 枚举 反射*/
private String v;
/**
*
*/
private Pair<Integer, Integer> pairThreadLocal;
public ThreadPoolInterfaceInvokeTwo(String v){
this.v = v;
}
@Override
public Pair<Integer, Integer> call() throws Exception {
// 枚举获得 类名称 或则 获得类.class
String serviceClass = ThreadEnumTwo.get(v).getServiceClass();
// 根据类名 或者.class获得反射类
// 这里需注意,如果是name的方式需要在@Service("ThreadThreeServiceImpl")注明,否则spring工厂找不到bean,当然也可以直接使用.class的方式。后续贴出代码,这里不展示
ThreadServiceBase bean = (ThreadServiceBase) SpringContextUtil.getBean(serviceClass);
Class<? extends ThreadServiceBase> aClass = bean.getClass();
// 获取方法 这里的方法名需要不同接口实现时使用相同的方法名
Method threadOne = aClass.getMethod("threadOne", null);
// 调用方法
int invokeOne = (int)threadOne.invoke(aClass.newInstance(), null);
Method threadTwo = aClass.getMethod("threadTwo", null);
int invokeTwo = (int)threadTwo.invoke(aClass.newInstance(), null);
logger.info("invokeOne name v:{}, invokeOne value:{}",v,threadOne);
logger.info("invokeTwo name v:{}, invokeTwo value:{}",v,threadTwo);
pairThreadLocal = new Pair<Integer, Integer>(invokeOne,invokeTwo);
return pairThreadLocal;
}
}
线程写好后,下一步是定义线程池。这里就不作赘述。
// 这里只贴出了上面的一种方式,其实两个都差不多。
// 我这里使用的springboot中自带的schdule方式,可以自行选择其他定时任务,quatz, xx_job,eslate_job,timer等都一样使用代码逻辑
@Async//此注解是config中的线程池使用定时任务。
@Component
public class ScheduleThradInterfaceTwo {
private static final org.slf4j.Logger log = LoggerFactory.getLogger(ScheduleThradInterfaceTwo.class);
@Scheduled(cron = "0 0/1 * * * ?")
public void scheduled() throws Exception{
log.info("ScheduleThradInterfaceTwo---------------------");
// 固定大小线程池的使用
ThreadPoolExecutor threadPool = new ThreadPoolExecutor(
2, //核心线程池大小
Runtime.getRuntime().availableProcessors(), //最大核心线程池大小(CPU密集型,根据CPU核数设置)
3, //超时了没有人调用就会释放
TimeUnit.SECONDS, //超时单位
new LinkedBlockingDeque<>(3), //阻塞队列
Executors.defaultThreadFactory(), //线程工厂,创建线程的,一般不用动
new ThreadPoolExecutor.AbortPolicy());
// 使用多线程 lsit 一起调用
List<ThreadPoolInterfaceInvokeTwo> list = Arrays.asList(
new ThreadPoolInterfaceInvokeTwo(ThreadEnum.THREADTHREE.getServiceName()),
new ThreadPoolInterfaceInvokeTwo(ThreadEnum.THREADONE.getServiceName()));
List<Future<Pair<Integer, Integer>>> futures = null;
try {
futures = threadPool.invokeAll(list);
} catch (InterruptedException e) {
e.printStackTrace();
}
List<Integer> integers = new ArrayList<>();
// 待结果统一返回后,整理结果集
futures.stream().forEach( fu -> {
try {
Pair<Integer, Integer> integerIntegerPair = fu.get();
integers.add(integerIntegerPair.getKey());
integers.add(integerIntegerPair.getValue());
} catch (InterruptedException e) {
e.printStackTrace();
} catch (ExecutionException e) {
e.printStackTrace();
}
});
log.info("ScheduleThradInterfaceTwo输出结果---------------------------------------------------------------------:"+integers.toString());
}
}
springContexUtils如下:
@Component
public class SpringContextUtil implements ApplicationContextAware {
public static ApplicationContext applicationContext;
@Override
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
SpringContextUtil.applicationContext = applicationContext;
}
public ApplicationContext getApplicationContext() {
return applicationContext;
}
public static Object getBean(String name) {
return applicationContext.getBean(name);
}
public <T> T getBean(Class<T> clazz) {
return applicationContext.getBean(clazz);
}
public <T> T getBean(String name, Class<T> clazz) {
return getApplicationContext().getBean(name, clazz);
}
}