
“嗨,阿米戈!”
“没有什么东西在最初创建时是完美的。线程也是如此。随着时间的推移,Java 的创建者开始确信 Runnable 接口的缺点。它不支持抛出异常,也无法找出执行任务的结果……”
“Runnable 接口更适合大型独立任务,而不是您想要一次运行十几个,然后收集它们的结果的小型子任务。”
“这就是发明Callable接口的原因。它比Runnable和Thread 更适合并行执行小任务,部分原因是它是一个通用接口。”
“这是接口的典型实现:”
例子
class ReverseString implements Callable<String>
{
String str;
ReverseString(String str)
{
this.str = str;
}
public String call() throws Exception
{
StringBuilder builder = new StringBuilder(str);
builder.reverse();
return builder.toString();
}
}
“与Runnable不同,这里我们需要重写 call 方法,该方法返回由类型参数指定的类型的结果。这种方法比 Runnable 接口的 run 方法返回 void 更方便。有时开发人员不得不想出获得线程结果的各种解决方法。”
“我懂了。”
“现在看看Callable如何与 ThreadPoolExecutor 一起工作:
“首先,ThreadPoolExecutor类的提交方法返回一个参数化的 Future 对象。您可以使用该对象来确定任务是否完成并获取结果。”
“这是它的工作原理:”
例子
// 1. Create a ThreadPoolExecutor
ExecutorService service = Executors.newFixedThreadPool(5);
// 2. Add a task to it
Future<String> task = service.submit(new ReverseString("Amigo"));
// 3. Wait until the task is done
while(!task.isDone()) { Thread.sleep(1); }
// 4. Try to get the result
//We will get either the result, or an exception if one occurred while the task was being executed
try { System.out.println("Full string : " + task.get()); } catch (Exception ie) { ie.printStackTrace(System.err); }
// 5. Stop the ThreadPool.
service.shutdown();
“扯远了!我特别喜欢Future类,它有什么方法?”
“这是最有趣的:”
方法 | 描述 |
---|---|
|
停止任务。 |
|
如果任务已停止,则返回 true。 |
|
如果任务完成执行则返回 true。 |
|
返回调用方法的结果,如果发生异常则抛出异常。 |
“酷!这样你也可以停止任务了。”
“不要过分依赖它——不是每个线程都能停止。但如果任务仍在队列中,那么它就可以正常工作。”
“我喜欢这种方法。它比自己创建线程然后尝试从中提取结果要方便得多。”
“太好了。今天我们就到这里结束。”
GO TO FULL VERSION