某些需要占用较长的执行时间可以用多线程异步方式执行。我们可以为这些异步任务赋予最大执行次数、执行时长限制、重试时间间隔等特性,以保证异步任务不会在失败的情况下一直占用系统资源不放。
父类实现
我们可以设置一个简单的线程类作为父类来承载这些特性。代码如下:
public class ConfigurableThread extends Thread {
private boolean firstExe = false;
private boolean enableTimeLimit = false;
private boolean enableExeLimit = false;
private Date firstExeTime;
private Long timeInterval = 1000L;
private Integer exeLimit = 0;
private Long timeLimit = 0L;
private Integer tryCount = 0;
protected boolean successFlag = false; //成功标志
@Override
public void run(){
if(!firstExe){
this.firstExe = true;
this.firstExeTime = new Date();
}
try {
while(execuble()){
// System.out.println("第 " + this.tryCount + " 次尝试");
doRun();
tryCount ++;
Thread.currentThread().sleep(this.timeInterval);
}
System.out.println("循环结束,退出");
return;
} catch (Exception e) {
System.out.println("doRun 出现异常 : "+ e);
}
}
public void doRun() throws Exception{
throw new Exception("还未声明实现方法");
}
private boolean execuble(){
if(enableTimeLimit &&
(new Date().getTime() - this.firstExeTime.getTime()) > this.timeLimit){
System.out.println("执行时间超时,线程结束");
return false;
}
if(enableExeLimit &&
this.tryCount > this.exeLimit){
System.out.println("尝试次数超出,线程结束");
return false;
}
if(successFlag){
System.out.println("任务执行成功,线程结束");
return false;
}
return true;
}
public final ConfigurableThread enableTimeLimit() {
this.enableTimeLimit = true;
return this;
}
public final ConfigurableThread disableTimeLimit() {
this.enableTimeLimit = false;
return this;
}
public final ConfigurableThread enableExeLimit() {
this.enableExeLimit = true;
return this;
}
public final ConfigurableThread disableExeLimit() {
this.enableExeLimit = false;
return this;
}
public final ConfigurableThread setExeLimit(Integer exeLimit) {
this.exeLimit = exeLimit;
return this;
}
public final ConfigurableThread setTimeLimit(Long timeLimit) {
this.timeLimit = timeLimit;
return this;
}
public final ConfigurableThread setInterval(Long interval) {
this.timeInterval = interval;
return this;
}
}
这样在创建具体的异步任务代码时就可以只专注于业务实现了。
子类继承
public class TaskOne extends ConfigurableThread{
private int i = 0;
private int id = 0;
public TaskOne(int id){this.id = id;}
@Override
public void doRun(){
System.out.println("线程 : " + this.id + " | 计算:"+ ++i);
}
}
其中doRun是必须重写的方法,如果不重写则会执行父类的doRun, 即:抛出异常。
效果如下:
在具体应用时候,由于设置特性的方法返回对象自身,因此可以快速设置对象的属性:
new TaskOne(1)//指定id
.enableExeLimit()//启用最大执行次数限制
.enableTimeLimit()//启用最大执行时间限制
.setTimeLimit(1000L)//设置最大执行次数
.setInterval(30L);//设置最大执行时间
具体效果如下:
任务成功时:
具体应用
具体应用可以直接调用新实例或者结合线程池使用:
//直接使用
new TaskOne(1)
.enableExeLimit()
.enableTimeLimit()
.setTimeLimit(1000L)
.setExeLimit(3)
.setInterval(30L)
.start();
//线程池
new TaskOne().enableTimeLimit().setTimeLimit(5500L).setInterval(30L).start();
BlockingQueue queue = new LinkedBlockingQueue<Runnable>(3);
pool.execute(
new TaskOne(i)
.enableExeLimit()
.setExeLimit(3)
.setInterval(1000L)
);