您的位置:首页 > 编程语言 > Java开发

Java 多线程设置线程超时时间之 Callable接口和Future接口 超时控制

2017-04-20 17:33 716 查看



Callable接口和Future接口介绍

        在Java中,如果需要设定代码执行的最长时间,即超时,可以用Java线程池ExecutorService类配合Future接口来实现。
Future接口是Java标准API的一部分,在java.util.concurrent包中。Future接口是Java线程Future模式的实现,可以来进行异步计算。

        Future模式可以这样来描述:我有一个任务,提交给了Future,Future替我完成这个任务。期间我自己可以去做任何想做的事情。一段时间之后,我就便可以从Future那儿取出结果。就相当于下了一张订货单,一段时间后可以拿着提订单来提货,这期间可以干别的任何事情。其中Future 接口就是订货单,真正处理订单的是Executor类,它根据Future接口的要求来生产产品。

        Future接口提供方法来检测任务是否被执行完,等待任务执行完获得结果,也可以设置任务执行的超时时间。这个设置超时的方法就是实现Java程序执行超时的关键。

        Future接口是一个泛型接口,严格的格式应该是Future<V>,其中V代表了Future执行的任务返回值的类型。 Future接口的方法介绍如下:
boolean cancel (boolean mayInterruptIfRunning) 取消任务的执行。参数指定是否立即中断任务执行,或者等等任务结束
boolean isCancelled () 任务是否已经取消,任务正常完成前将其取消,则返回 true
boolean isDone () 任务是否已经完成。需要注意的是如果任务正常终止、异常或取消,都将返回true
get () throws InterruptedException, ExecutionException  等待任务执行结束,然后获得V类型的结果。InterruptedException 线程被中断异常, ExecutionException任务执行异常,如果任务被取消,还会抛出
CancellationException

get (long timeout, TimeUnit unit) throws InterruptedException, ExecutionException, TimeoutException 同上面的get功能一样,多了设置超时时间。参数timeout指定超时时间,uint指定时间的单位,在枚举类TimeUnit中有相关的定义。如果计算超时,将抛出TimeoutException

         Future的实现类有java.util.concurrent.FutureTask<V>即 javax.swing.SwingWorker<T,V>。通常使用FutureTask来处理我们的任务。FutureTask类同时又实现了Runnable接口,所以可以直接提交给Executor执行。使用FutureTask实现超时执行的代码如下:

ExecutorService executor = Executors.newSingleThreadExecutor();
FutureTask<String> future =
new FutureTask<String>(new Callable<String>() {//使用Callable接口作为构造参数
public String call() {
//真正的任务在这里执行,这里的返回值类型为String,可以为任意类型
}});
executor.execute(future);
//在这里可以做别的任何事情
try {
result = future.get(5000, TimeUnit.MILLISECONDS); //取得结果,同时设置超时执行时间为5秒。同样可以用future.get(),不设置执行超时时间取得结果
} catch (InterruptedException e) {
futureTask.cancel(true);
} catch (ExecutionException e) {
futureTask.cancel(true);
} catch (TimeoutException e) {
futureTask.cancel(true);
} finally {
executor.shutdown();
}
例1try catch在for循环之外, futureTask.cancel(true); 取消后不再执行;try catch在for循环内, futureTask.cancel(true); 取消后继续执行
package testexception;

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;

public class FutureTaskTest{
public static void main(String[] args) {
ExecutorService executor = Executors.newSingleThreadExecutor();
FutureTask futureTask =
new FutureTask(new Callable() {//使用Callable接口作为构造参数
public String call() {
/*
* 例1:try catch在for循环之外,  futureTask.cancel(true);  取消后不再执行;
try {
for (int i = 0; i < 5; i++) {
Thread.sleep(1000);
System.out.println("------------------------"+i);
}
} catch (InterruptedException e) {
System.out.println("InterruptedException ");
e.printStackTrace();
}  */
//try catch在for循环内,  futureTask.cancel(true);  取消后继续执行
try {
for (int i = 0; i < 5; i++) {
Thread.sleep(1000);
System.out.println("------------------------"+i);
}
} catch (InterruptedException e) {
System.out.println("InterruptedException1111111");
e.printStackTrace();
}
//真正的任务在这里执行,这里的返回值类型为String,可以为任意类型
return "call result";
}});
executor.execute(futureTask);
//在这里可以做别的任何事情
try {
String result = futureTask.get(3000, TimeUnit.MILLISECONDS);
//取得结果,同时设置超时执行时间为5秒。同样可以用future.get(),不设置执行超时时间取得结果
System.out.println("___________"+result+"_______________");
} catch (InterruptedException e) {
System.out.println("InterruptedException ");
futureTask.cancel(true);
} catch (ExecutionException e) {
System.out.println("ExecutionException ");

4000
futureTask.cancel(true);
} catch (TimeoutException e) {
System.out.println("!!!!!!!!Time out!!!!!!!!!!");
futureTask.cancel(true);  //取消执行的线程
} finally {
executor.shutdown();
}
}
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  多线程 java
相关文章推荐