简单说明:
- Callable接口类似于Runnable,但是Runnable不会返回结果,并且无法抛出返回结果的异常,而Callable功能更强大一些,被线程执行后,可以返回值,这个返回值可以被Future拿到。
- FutureTask实现了两个接口,Runnable和Future,所以它既可以作为Runnable被线程执行,又可以作为Future得到Callable的返回值。假设有一个很耗时的返回值需要计算,并且这个返回值不是立刻需要的话,那么就可以使用这个组合,用另一个线程去计算返回值,而当前线程在使用这个返回值之前可以做其它的操作,等到需要这个返回值时,再通过Future得到。
Callable说明:
Callbale接口是一个参数化的类型,只有一个方法call。
public interface Callable<V>
{
V call() throw Exception;
}
- 类型参数是返回值的类型。例如,Callable<Integer>表示一个最终返回Integer的异步计算。
Future用法:
java.util.concurrent.Future 是一个异步回调接口,保存异步计算的结果。
- Future接口具有下面方法:
public interface Future<V>
{
V get() throws ...;
V get(long timeout, TimeUnit unit) throws ...;
void cancel(boolean mayInterrupt);
boolean isCancelled();
boolean isDone();
}
用例:
public class CallableFuture {
public static void main(String[] args) throws InterruptedException, Exception {
ExecutorService exec = Executors.newCachedThreadPool();
// Future是一个接口,该接口用来返回异步的结果。
Future<String> st = exec.submit(new TaskCallable());
System.out.println("finished");
}
}
class TaskCallable implements Callable<String> {
public String call() throws Exception {
Thread.sleep(2000);
return "callstatus=OK";
}
}
java.util.concurrent.Future<V>
- V get()
-
V get(long time, TimeUnit unit)
获取结果,如果没有结果可用,则阻塞直到真正得到结果超过指定的时间为止。如果不成功,第二个方法会抛出TimeoutException异常。 -
boolean cancel(boolean mayInterrupt)
尝试取消一任务的运行。如果任务已经开始,并且mayInterrupt参数值为true,它就会被中断。如果成功执行了取消操作,返回true。 -
boolean isCancelled()
如果任务在完成前被取消了,则返回true。 -
boolean isDone()
如果任务结束,无论是正常结束、中途取消或发生异常,都返回true。
FutureTask用法:
FutureTask实现了java.util.concurrent.RunnableFuture<V>接口,实际上实现了Runnable和 Future<V>两个接口。
java.util.concurrent.FutureTask<V>
- FutureTask(Callable<V> task)
-
FutureTask(Runnable task, V result)
构造一个既是Future<V>又是Runnable的对象。
用例:
public class MyFutureTask {
public static void main(String[] args) {
Callable<int[]> primeCallable = new PrimeCallable(1000);
FutureTask<int[]> primeTask = new FutureTask<int[]>(primeCallable);
Thread t = new Thread(primeTask);
t.start();
try {
// 假设现在做其他事情
Thread.sleep(5000);
// 回来看看质数找好了吗
if (primeTask.isDone()) {
int[] primes = primeTask.get();
for (int prime : primes) {
System.out.print(prime + " ");
}
System.out.println();
}
} catch (InterruptedException e) {
e.printStackTrace();
} catch (ExecutionException e) {
e.printStackTrace();
}
}
}
class PrimeCallable implements Callable<int[]> {
private int max;
public PrimeCallable(int max) {
this.max = max;
}
public int[] call() throws Exception {
int[] prime = new int[max + 1];
List<Integer> list = new ArrayList<Integer>();
for (int i = 2; i <= max; i++)
prime[i] = 1;
for (int i = 2; i * i <= max; i++) { // 这里可以改进
if (prime[i] == 1) {
for (int j = 2 * i; j <= max; j++) {
if (j % i == 0)
prime[j] = 0;
}
}
}
for (int i = 2; i < max; i++) {
if (prime[i] == 1) {
list.add(i);
}
}
int[] p = new int[list.size()];
for (int i = 0; i < p.length; i++) {
p[i] = list.get(i).intValue();
}
return p;
}
}
网友评论