1. 介绍Runnable和Callable

创建线程类一般使用的方式有三种:

  1. 继承Thread调用start方法
  2. 实现Runnable接口调用run方法
  3. 实现Callable接口调用call方法

如今,第一种方式肯定是差不多淘汰了。因为用继承约束很大。

关于使用Runnable和Callable接口的异同在StackoverFlow的一篇帖子The difference between the Runnable and Callable interfaces in Java中说的比较清楚。

主要区别就是:

  1. Runnable能做得,Callable都能做。但是Callable能做的,Runnable不一定能做。
  2. Callable的call方法可以有返回值
  3. Callable方法可以抛出异常
  4. 支持ExecutorServer当中的invokeAny和invokeAll方法

总结: 所以现在写代码还是多用Callable吧

PS:JAVA1.5之后引入了Callable和Future

2. ExecutorService中的submit方法、executor方法和invokeXXX方法

2.1 submit方法和executor方法区别

  1. submit方法可以接受Runnable对象或者是Callable对象而executor只能接受Runnable对象。
  2. submit方法会有Future对象返回,executor方法不会有返回值

2.2 submit方法接受Callable对象和接受Runnable对象的区别

之前说过Runnable对象调用run后没有返回结果。所以任务完成后,虽然会返回Future对象,但是实际上调用get方法得到的是null。而如果是Callable对象作为参数给submit方法,那么最后完成任务后的Future对象中可以get到call得结果。

PS: 这里虽然一直说Future对象,但是要知道实际使用中返回的是其实现Future接口的FutureTask类哦~

2.3 submit方法和invoke方法区别

  1. invokeXXX和submit的主要区别是其接受的参数是一个Callable的集合(Set)
  2. invokeAny和invokeAll的区别是invokeAny返回任意一个执行完毕的call方法的返回值;invokeAll返回一个Future对象的List