问题是这样的,我有个程序段,但这个程序段执行的时间长短是未知的,我想用用代码控制这个程序段,如果超过了我指定的时间,我就中断那一段程序。在网上搜了下,找到如下一段超时处理的程序。二.实现方法 方法1.(原创) 实现描述:使用一个守护线程作为计时器,并且在计时结束时抛出一个未检测异常。 具体实现: 类1:守护线程类 /**
* 本线程设置了一个超时时间
* 该线程开始运行后,经过指定超时时间,
* 该线程会抛出一个未检查异常通知调用该线程的程序超时
* 在超时结束前可以调用该类的cancel方法取消计时
* @author solonote
*/
public class TimeoutThread extends Thread{
/**
* 计时器超时时间
*/
private long timeout;
/**
* 计时是否被取消
*/
private boolean isCanceled = false;
/**
* 当计时器超时时抛出的异常
*/
private TimeoutException timeoutException;
/**
* 构造器
* @param timeout 指定超时的时间
*/
public TimeoutThread(long timeout,TimeoutException timeoutErr) {
super();
this.timeout = timeout;
this.timeoutException = timeoutErr;
//设置本线程为守护线程 this.setDaemon(true);
}
/**
* 取消计时
*/
public synchronized void cancel()
{
isCanceled = true;
}
/**
* 启动超时计时器
*/
public void run()
{
try {
Thread.sleep(timeout);
if(!isCanceled)
throw timeoutException;
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
注: 类一中的TimeoutException是下边的用户自定义类,不是java中的java.util.concurrent.TimeoutException 类2.抛出异常类,该类继承了RuntimeException,原因是run方法不能抛出已检测异常。 public class TimeoutException extends RuntimeException {
/**
* 序列化号
*/
private static final long serialVersionUID = -8078853655388692688L;
public TimeoutException(String errMessage)
{
super(errMessage);
}
}
使用方法: //初始化超时类 TimeoutThread t = new TimeoutThread(5000,new TimeoutException("超时"));
try{
t.start();
.....要检测超时的程序段....
t.cancel();
}catch (TimeoutException e)
{
...对超时的处理...
}
TimeoutException可以更换为其他未检查异常类。执行程序时,发现下面这一部分:
TimeoutThread t = new TimeoutThread(5000,new TimeoutException("超时"));
try{
t.start();
.....要检测超时的程序段....
t.cancel();
}catch (TimeoutException e)
{
...对超时的处理...
}中的TimeoutException 我catch不到,程序不会执行我在catch中写的处理。请高手指点下。是不是因为TimeoutException 是运行时异常,所以无法捕捉? 另外像我描述的这种超时处理,大家一般是怎么处理。谢谢。
* 本线程设置了一个超时时间
* 该线程开始运行后,经过指定超时时间,
* 该线程会抛出一个未检查异常通知调用该线程的程序超时
* 在超时结束前可以调用该类的cancel方法取消计时
* @author solonote
*/
public class TimeoutThread extends Thread{
/**
* 计时器超时时间
*/
private long timeout;
/**
* 计时是否被取消
*/
private boolean isCanceled = false;
/**
* 当计时器超时时抛出的异常
*/
private TimeoutException timeoutException;
/**
* 构造器
* @param timeout 指定超时的时间
*/
public TimeoutThread(long timeout,TimeoutException timeoutErr) {
super();
this.timeout = timeout;
this.timeoutException = timeoutErr;
//设置本线程为守护线程 this.setDaemon(true);
}
/**
* 取消计时
*/
public synchronized void cancel()
{
isCanceled = true;
}
/**
* 启动超时计时器
*/
public void run()
{
try {
Thread.sleep(timeout);
if(!isCanceled)
throw timeoutException;
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
注: 类一中的TimeoutException是下边的用户自定义类,不是java中的java.util.concurrent.TimeoutException 类2.抛出异常类,该类继承了RuntimeException,原因是run方法不能抛出已检测异常。 public class TimeoutException extends RuntimeException {
/**
* 序列化号
*/
private static final long serialVersionUID = -8078853655388692688L;
public TimeoutException(String errMessage)
{
super(errMessage);
}
}
使用方法: //初始化超时类 TimeoutThread t = new TimeoutThread(5000,new TimeoutException("超时"));
try{
t.start();
.....要检测超时的程序段....
t.cancel();
}catch (TimeoutException e)
{
...对超时的处理...
}
TimeoutException可以更换为其他未检查异常类。执行程序时,发现下面这一部分:
TimeoutThread t = new TimeoutThread(5000,new TimeoutException("超时"));
try{
t.start();
.....要检测超时的程序段....
t.cancel();
}catch (TimeoutException e)
{
...对超时的处理...
}中的TimeoutException 我catch不到,程序不会执行我在catch中写的处理。请高手指点下。是不是因为TimeoutException 是运行时异常,所以无法捕捉? 另外像我描述的这种超时处理,大家一般是怎么处理。谢谢。
private boolean isCanceled = false;
private TimeoutException timeoutException; public TimeoutThread(long timeout, TimeoutException timeoutErr) {
super();
this.timeout = timeout;
this.timeoutException = timeoutErr;
}
public synchronized void cancel(){
this.isCanceled = true;
}
public void run() {
try {
Thread.sleep(timeout);
if(!isCanceled){
throw timeoutException;
}
} catch (InterruptedException e) {
}
}}
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
import java.util.concurrent.TimeUnit;public class TimeoutTest { public static void main(String[] args) { final ExecutorService service = Executors.newFixedThreadPool(1);
TimeoutThread timeoutThread = new TimeoutThread(5000, new TimeoutException("This my own timeout"));
Future future = service.submit(timeoutThread);
try {
try {
future.get(0l, TimeUnit.MILLISECONDS);
} catch (Exception e) {
if(e.getCause() instanceof TimeoutException){
throw new TimeoutException("Timeout from 0"); //0
}
}
Thread.sleep(1000);
try {
future.get(0l, TimeUnit.MILLISECONDS);
} catch (Exception e) {
if(e.getCause() instanceof TimeoutException){
throw new TimeoutException("Timeout from 1"); //1
}
}
Thread.sleep(5000);
try {
future.get(0l, TimeUnit.MILLISECONDS);
} catch (Exception e) {
if(e.getCause()instanceof TimeoutException){
throw new TimeoutException("Timeout from 2"); //2
}
}
Thread.sleep(3000);
try {
future.get(0l, TimeUnit.MILLISECONDS);
} catch (Exception e) {
if(e.getCause() instanceof TimeoutException){
throw new TimeoutException("Timeout from 3"); //3
}
}
timeoutThread.cancel();
} catch (Exception e) {
System.out.println(e.getMessage());
} finally{
service.shutdownNow();
}
}
}上面的代码虽然可以利用TimeoutException来检验是否Timeout,但要每执行一阵主程序就检验一次,代码比较乱,时间控制也不精确。于是有了下面的方案:import java.util.concurrent.Callable;public class TaskThread implements Callable<Long> {
private long taskRunningTime;
private long taskStartTime; public Long call() throws Exception {
taskStartTime = System.currentTimeMillis();
try {
Thread.sleep(2000);
} catch (Exception e) {
System.out.println("Task is interrupted!");
taskRunningTime = System.currentTimeMillis() - taskStartTime;
}
taskRunningTime = System.currentTimeMillis() - taskStartTime;
return taskRunningTime ;
}}
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
import java.util.concurrent.TimeUnit;public class TimeoutTest1 { public static void main(String[] args) {
final ExecutorService service = Executors.newFixedThreadPool(2); TimeoutThread timeoutThread = new TimeoutThread(5000,
new TimeoutException("This my own timeout"));
TaskThread taskThread = new TaskThread(); Future timeoutFuture = service.submit(timeoutThread); long taskRunningTime;
long taskStartTime;
taskStartTime = System.currentTimeMillis();
Future taskFuture = service.submit(taskThread);
try {
timeoutFuture.get(6000, TimeUnit.MILLISECONDS);
} catch (Exception e) {
if (e.getCause() instanceof TimeoutException) {
try {
if (taskFuture.cancel(true)) { taskRunningTime = System.currentTimeMillis() - taskStartTime;
System.out.println("Task might be interrupted.\nTask Running Time is: "
+ taskRunningTime/1000 + " seconds."); } else {
System.out.println("Task might be finished.\nTask Running Time is: "
+ ((Long) (taskFuture.get()))/1000 + " seconds.");
}
} catch (InterruptedException e1) {
e1.printStackTrace();
} catch (ExecutionException e1) {
e1.printStackTrace();
}
}
} finally {
service.shutdownNow();
}
}}上面代码的思路是:把实际要执行任务放到那个TaskThread里。这个TaskThread是一个Callable,所以可以返回一个值给主程序。在出程序里我们用:
timeoutFuture.get(6000, TimeUnit.MILLISECONDS);
来判断是否Timeout,如果Timeout,我们会用:
taskFuture.cancel(true)
来终止TaskThread的运行。这样思路就清晰多了。
用Future<T>.get(long timeout, TimeUnit unit);等任务执行完的结果,
如果没有执行完,直接ExecutorService.shutdownNow()杀掉线程池。
FutureTask<String> future = new FutureTask<String>(new Callable<String>() {// 使用Callable接口作为构造参数
public String call() {
//程序执行代码
return null;
}
});
executor.execute(future);
// 在这里可以做别的任何事情
try {
future.get(60000, TimeUnit.MILLISECONDS); //取得结果,同时设置超时执行时间为10秒。同样可以用future.get(),不设置执行超时时间取得结果
} catch (InterruptedException e) {
e.printStackTrace();
} catch (ExecutionException e) {
e.printStackTrace();
} catch (TimeoutException e) {
e.printStackTrace();
} finally {
executor.shutdown();
}我使用的这个 不过发现很奇怪的问题,前几天测试的时候还是好的,今天测试的时候cpu竟然达到99%