笔者在平常的项目开发中,会遇到有些程序执行时间过长的问题(比如查询数据库的时间过长,或者调用某一接口执行的时间过长),导致程序长时间卡死,因此,需要对程序进行超时中断处理,给程序的执行时间设定一个时间范围限制,如果超过这一范围,则进行中断处理,包括中断线程并且返回超时的结果。有时候线程已经在执行了,是无法中断的,程序要返回超时的结果,只是线程会继续执行,直到线程执行完成。
下面将介绍两种超时中断处理的实现方法,方法一是本人自己利用线程实现的,方法二则利用JDK自带的工具类FutureTask。
1、方法一
import java.util.Date;
public class TaskThread extends Thread {
private Task task;
public TaskThread(Task task) {
this.task = task;
}
public void run() {
int i = 0;
while(true && i < 10){
if(Task.STATUS_INTERRUPT.equals(task.getStatus())){
System.out.println(“线程执行中断”);
break;
}
System.out.println(new Date().toLocaleString()+”:每隔1秒打印一下日志”);
try {
Thread.sleep(1*1000);
i++;
} catch (InterruptedException e) {
e.printStackTrace();
}
}
task.setStatus(Task.STATUS_FINISHED);
System.out.println(“线程执行完成”);
}
}
import java.util.Date;
public class Task {
public static final String STATUS_START = “START”;
public static final String STATUS_FINISHED = “FINISHED”;
public static final String STATUS_INTERRUPT = “INTERRUPT”;
private String status = “”;
private Date startTime = null;
private TaskThread taskThread = null;
public void setStatus(String status) {
this.status = status;
}
public String execute() {
this.setStatus(Task.STATUS_START);
startTime = new Date();
taskThread = new TaskThread(this);
try{
taskThread.start();
}catch (Exception e) {
e.printStackTrace();
}
String result = “”;
while(true){
if(Task.STATUS_FINISHED.equals(this.getStatus())){
result = “任务执行成功”;
break;
}
Date currentTime = new Date();
if((currentTime.getTime() – this.getStartTime().getTime()) > 5*1000){
this.setStatus(Task.STATUS_INTERRUPT);
result = “任务执行中断”;
System.out.println(“线程执行超时:限定时间是5秒!”);
break;
}
}
return result;
}
public String getStatus() {
return status;
}
public Date getStartTime() {
return startTime;
}
public void setStartTime(Date startTime) {
this.startTime = startTime;
}
}
/**
* 当任务执行超时或者执行过程出现错误时,实现任务中断功能。
* @author brushli
* @date 2013-10-05
*
*/
public class InterruptExample {
public static void main(String[] args) {
Task task = new Task();
String execute = task.execute();
System.out.println(“result=”+execute);
}
}
程序执行的结果:
2013-10-5 15:10:45:每隔1秒打印一下日志
2013-10-5 15:10:46:每隔1秒打印一下日志
2013-10-5 15:10:47:每隔1秒打印一下日志
2013-10-5 15:10:48:每隔1秒打印一下日志
2013-10-5 15:10:49:每隔1秒打印一下日志
线程执行超时:限定时间是5秒!
result=任务执行中断
线程执行中断
线程执行完成
更改一下类Task中的代码,将超时的时间范围设定为50秒
if((currentTime.getTime() – this.getStartTime().getTime()) > 50*1000){
this.setStatus(Task.STATUS_INTERRUPT);
result = “任务执行中断”;
System.out.println(“线程执行超时:限定时间是50秒!”);
break;
}
此时程序的执行结果是:
2013-10-5 15:12:11:每隔1秒打印一下日志
2013-10-5 15:12:12:每隔1秒打印一下日志
2013-10-5 15:12:13:每隔1秒打印一下日志
2013-10-5 15:12:14:每隔1秒打印一下日志
2013-10-5 15:12:15:每隔1秒打印一下日志
2013-10-5 15:12:16:每隔1秒打印一下日志
2013-10-5 15:12:17:每隔1秒打印一下日志
2013-10-5 15:12:18:每隔1秒打印一下日志
2013-10-5 15:12:19:每隔1秒打印一下日志
2013-10-5 15:12:20:每隔1秒打印一下日志
线程执行完成
result=任务执行成功
2、方法二
利用JDK自带的工具类:FutureTask
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.FutureTask;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;
/**
* 当任务执行超时或者执行过程出现错误时,实现任务中断功能。
* @author brushli
* @date 2013-10-05
*
*/
public class InterruptTest {
public static void main(String[] args) {
System.out.println(“result=”+new InterruptTest().getResult());
}
public String getResult() {
ExecutorService executorService = Executors.newSingleThreadExecutor();
FutureTask future = new FutureTask(new Callable() {
public String call() throws Exception {
InterruptTest interrupt = new InterruptTest();
return interrupt.getValue();
}
});
executorService.execute(future);
String result = null;
try{
//设定超时的时间范围为10秒
result = future.get(10, TimeUnit.SECONDS);
}catch (InterruptedException e) {
future.cancel(true);
System.out.println(“方法执行中断”);
}catch (ExecutionException e) {
future.cancel(true);
System.out.println(“Excution异常”);
}catch (TimeoutException e) {
future.cancel(true);
result = “方法执行时间超时”;
}
executorService.shutdownNow();
return result;
}
public String getValue()
{
try{
Thread.sleep(5000);
System.out.println(“正常执行”);
}catch (Exception e) {
e.printStackTrace();
}
return “正常结果”;
}
}
程序运行的结果是:
正常执行
result=正常结果
修改一下超时的时间:
//设定超时的时间范围为3秒
result = future.get(3, TimeUnit.SECONDS);
程序运行的结果是:
java.lang.InterruptedException: sleep interruptedresult=方法执行时间超时
at java.lang.Thread.sleep(Native Method)
at com.interrupt.InterruptTest.getValue(InterruptTest.java:48)
at com.interrupt.InterruptTest$1.call(InterruptTest.java:23)
at com.interrupt.InterruptTest$1.call(InterruptTest.java:1)
at java.util.concurrent.FutureTask$Sync.innerRun(FutureTask.java:303)
at java.util.concurrent.FutureTask.run(FutureTask.java:138)
at java.util.concurrent.ThreadPoolExecutor$Worker.runTask(ThreadPoolExecutor.java:886)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:908)
at java.lang.Thread.run(Thread.java:662)