1. 介绍Runnable和Callable
创建线程类一般使用的方式有三种:
- 继承Thread调用start方法
- 实现Runnable接口调用run方法
- 实现Callable接口调用call方法
如今,第一种方式肯定是差不多淘汰了。因为用继承约束很大。
关于使用Runnable和Callable接口的异同在StackoverFlow的一篇帖子The difference between the Runnable and Callable interfaces in Java中说的比较清楚。
主要区别就是:
- Runnable能做得,Callable都能做。但是Callable能做的,Runnable不一定能做。
- Callable的call方法可以有返回值
- Callable方法可以抛出异常
- 支持ExecutorServer当中的invokeAny和invokeAll方法
总结: 所以现在写代码还是多用Callable吧
PS:JAVA1.5之后引入了Callable和Future
2. ExecutorService中的submit方法、executor方法和invokeXXX方法
2.1 submit方法和executor方法区别
- submit方法可以接受Runnable对象或者是Callable对象而executor只能接受Runnable对象。
- 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方法区别
- invokeXXX和submit的主要区别是其接受的参数是一个Callable的集合(Set)
- invokeAny和invokeAll的区别是invokeAny返回任意一个执行完毕的call方法的返回值;invokeAll返回一个Future对象的List