说明
本文介绍的是利用Java 并发工具箱concurrent包,实现对指定类中指定方法的执行时间的控制。
存在于 java.util.concurrent 包里的 ExecutorService 实现就是一个线程池的实现,包里定义了三个Executor接口:
a. Executor:一个运行新任务的简单接口。
b. ExecutorService:扩展了Executor接口。添加了一些用来管理执行器生命周期和任务生命周期的方法。
c. ScheduledExecutorService:扩展了ExecutorService。支持Future和定期执行任务。
Java的线程池有四种:
a. newCachedThreadPool —— 可缓存线程池,若线程池长度超过处理需要,则回收空线程,否则创建新线程,线程规模可无限大。且若当执行第二个任务时第一个任务已经完成,会复用执行第一个任务的线程,而不用每次新建线程。
ExecutorService cachedThreadPool = Executors.newCachedThreadPool();
b. newFixedThreadPool —— 定长线程池,可控制线程最大并发数,超出的线程会在队列中等待。
// t_num 最大线程数
ExecutorService fixedThreadPool = Executors.newFixedThreadPool(t_num);
c. newScheduledThreadPool —— 定长线程池,支持定时的及周期性的任务执行,类似Timer。
// t_num 最大线程数(int)
ScheduledExecutorService scheduledThreadPool = Executors.newScheduledThreadPool(t_num);
// 第一个参数是一个Runnable
// time_delay 延时时间(int)
// time_cycle 执行周期时间(int)
// 最后一个就是时间单位啦
scheduledThreadPool.scheduleAtFixedRate(new Runnable() {
@Override
public void run() {
// 执行方法
}
}, time_delay, time_cycle, TimeUnit.xxx);
// 意思就是延迟time_delay秒后每time_cycle秒执行一次。
d. newSingleThreadExecutor —— 单线程 的线程池,支持FIFO, LIFO, 优先级策略。
接下来需要说明的就是Callable和Future
创建线程的2种方式,一种是直接继承Thread,另外一种就是实现Runnable接口。这2种方式都有一个缺陷就是:在执行完任务之后无法获取执行结果。如果需要获取执行结果,就必须通过共享变量或者使用线程通信的方式来达到效果,这样使用起来就比较麻烦。而自从Java 1.5开始,就提供了Callable和Future,通过它们可以在任务执行完毕之后得到任务执行结果。在线程池提交Callable任务后返回了一个Future对象,使用它可以知道Callable任务的状态和得到Callable返回的执行结果。Future提供了get()方法让我们可以等待Callable结束并获取它的执行结果。
代码
public class TimeOutUtil {
private long timeout; // 超时时间
private ExecutorService exec;
private Callable call;
private Future future;
// 构造方法,我们需要初始化超时时间和最大线程数
public TimeOutUtil(long timeout,int nMethod) {
this.timeout = timeout;
this.exec = Executors.newFixedThreadPool(nMethod);
}
// 监控方法
// 参数(指定方法,指定类,方法的参数)
// 返回方法执行的结果“正常结果”或“超时”或“其他异常”
public Object checkTimeOut(Method method, Object theObj,Object param){
System.out.println("LOG : get method "+method.getName());
try {
this.call = new Callable() {
@Override
public Object call() throws Exception {
if(null != param) {
return method.invoke(theObj, param);
}
else
return method.invoke(theObj,null);
}
};
this.future = this.exec.submit(this.call);
Object result = future.get(this.timeout, TimeUnit.MILLISECONDS);
// 这里做了一下处理,如果方法是一个void就变成Boolean
if(method.getReturnType() == void.class)
return true;
return result;
} catch (TimeoutException e){
System.out.println("ERROR : TimeOut");
if(method.getReturnType() == Boolean.class||
method.getReturnType() == void.class)
return false;
else return null;
} catch (Exception e){
e.printStackTrace();
return null;
}
}
// 关闭
public void shutdown(){
if(!this.exec.isShutdown())
this.exec.shutdown();
}
}
使用
// 初始化
TimeOutUtil timeOutUtil = new TimeOutUtil(timeout,t_num);
// T 方法返回类型
// TheClass 指定类
// methodName 方法名
// params_type 方法参数类型
// params 方法参数
T rel = (T)timeOutUtil
.checkTimeOut(TheClass.class.getMethod(methodName,params_type),
this,
params);
// 别忘了关
timeOutUtil.shutdown();