执行器、执行器服务、执行器 - 1

“嗨,阿米戈!”

“没有什么东西在最初创建时是完美的。线程也是如此。随着时间的推移,Java 的创建者开始确信 Runnable 接口的缺点。它不支持抛出异常,也无法找出执行任务的结果……”

“Runnable 接口更适合大型独立任务,而不是您想要一次运行十几个,然后收集它们的结果的小型子任务。”

“这就是发明Callable接口的原因。它比RunnableThread 更适合并行执行小任务,部分原因是它是一个通用接口。”

“这是接口的典型实现:”

例子
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类,它有什么方法?”

“这是最有趣的:”

方法 描述
boolean cancel(boolean mayInterrupt);
停止任务。
boolean isCancelled();
如果任务已停止,则返回 true。
boolean isDone();
如果任务完成执行则返回 true。
V get() throws InterruptedException, ExecutionException;
返回调用方法的结果,如果发生异常则抛出异常。

“酷!这样你也可以停止任务了。”

“不要过分依赖它——不是每个线程都能停止。但如果任务仍在队列中,那么它就可以正常工作。”

“我喜欢这种方法。它比自己创建线程然后尝试从中提取结果要方便得多。”

“太好了。今天我们就到这里结束。”