版权声明:本文为 @WildMeowth 的原创文章,可以转载,但请务必注明作者和出处!!!原文链接:wildmeowth
Callable 接口和Runnable 接口相似, 但两者也有很关键的区别. Callable 可以返回结果, Runnable 不会返回结果. 因此相对来说Callable功能更加强大.
和Runnable的run() 方法类似, Callable有一个Call() 方法, 我们可以先创建一个新的Callable, 然后使用Callable的 call() 方法, 得到返回的结果.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
public static void main(String[] args) throws Exception {
Long before = System.currentTimeMillis();
Callable<String> callable = new Callable<String>(){
@Override
public String call() throws Exception {
Thread.sleep(4000);// 可能做一些事情
return "Test Callable ";
}
};
System.out.println(callable.call()+callable.call());// 输出Test Callable Test Callable
long after = System.currentTimeMillis();
System.out.println(after-before);// 输出8009
}
如上例子, 我们call了名为callable的线程两次, 显而易见第一个System.out.println得到的结果是
Test Callable Test Callable
第二个System.out.println得到的结果大约是8000+, 表明运行两次该线程所需要的时间大约是8000+毫秒
利用Future 也可以得到Callable返回的值, 如下
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
public static void main(String[] args) throws Exception {
Long before = System.currentTimeMillis();
Callable<String> callable = new Callable<String>(){
@Override
public String call() throws Exception {
Thread.sleep(4000);// 可能做一些事情
return "Test Callable";
}
};
ExecutorService threadPool = Executors.newSingleThreadExecutor();
Future<String> future = threadPool.submit(callable);
System.out.println(future.get()+future.get());// 输出Test Callable Test Callable
//System.out.println(callable.call()+callable.call());
long after = System.currentTimeMillis();
System.out.println(after-before);// 输出4006
}
此时, 第一个System.out.println依旧得到Test Callable Test Callable
第二个System.out.println得到结果大约为4000+, 表明运行两次线程只需要4000+毫秒, 即两次线程异步执行不会互相干扰。
ExecutorService继承自Executor,它的目的是为我们管理Thread对象,从而简化并发编程。
除此之外, FutureTask也可以对Callable 异步获得返回值.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
public static void main(String[] args) throws Exception {
Long before = System.currentTimeMillis();
Callable<String> callable = new Callable<String>(){
@Override
public String call() throws Exception {
Thread.sleep(4000);// 可能做一些事情
return "Test Callable";
}
};
FutureTask<String> future = new FutureTask<String>(callable);
new Thread(future).start();
try {
Thread.sleep(1000);// 可能做一些事情
System.out.println(future.get());
} catch (InterruptedException e) {
e.printStackTrace();
} catch (ExecutionException e) {
e.printStackTrace();
}
long after = System.currentTimeMillis();
System.out.println(after-before);// 输出4006
}
FutureTask 实现了Future和Runnable两个接口, 意味着可以同时处理Runnable和Future, 它的好处在于如果有一个返回值计算需要很久, 这个返回值不需要立刻得到, 但线程中其他代码需要被尽快执行的时候, 使用FutureTask, 可以先做其他事, 等到结果计算完了再返回结果。