1.基本接口
- Runnable位于java.lang包下
- Callable位于java.util.concurrent包下
2.运行机制
2.1 Runable
JDK8中Runnable接口源码如下:
@FunctionalInterface
public interface Runnable {
/**
* When an object implementing interface <code>Runnable</code> is used
* to create a thread, starting the thread causes the object's
* <code>run</code> method to be called in that separately executing
* thread.
* <p>
* The general contract of the method <code>run</code> is that it may
* take any action whatsoever.
*
* @see java.lang.Thread#run()
*/
public abstract void run();
}从源码到Runnable接口是一个函数式接口只有一个抽象方法run(),且Runnable是没有返回值的。通过实现该接口创建任务类,将任务逻辑写在run()方法中,并将任务类对象传给Thread类的构造方法,运行它的start()方方法启动线程执行异步任务对象,但任务完成后无法返回任何结果。
其实Thread类也继承了Runnable接口。其部分源码如下:
public class Thread implements Runnable {
/* What will be run. */
private Runnable target;
@Override
public void run() {
if (target != null) {
target.run();
}
}
public synchronized void start() {
/**
* This method is not invoked for the main method thread or "system"
* group threads created/set up by the VM. Any new functionality added
* to this method in the future may have to also be added to the VM.
*
* A zero status value corresponds to state "NEW".
*/
if (threadStatus != 0)
throw new IllegalThreadStateException();
/* Notify the group that this thread is about to be started
* so that it can be added to the group's list of threads
* and the group's unstarted count can be decremented. */
group.add(this);
boolean started = false;
try {
start0();
started = true;
} finally {
try {
if (!started) {
group.threadStartFailed(this);
}
} catch (Throwable ignore) {
/* do nothing. If start0 threw a Throwable then
it will be passed up the call stack */
}
}
}
private native void start0();......}Thread通过执行start()方法中的strart0()创建线程并在start0()中调用run()方法执行。
2.2 Callable接口
Callable接口JDK8源码如下:
@FunctionalInterface
public interface Callable<V> {
/**
* Computes a result, or throws an exception if unable to do so.
*
* @return computed result
* @throws Exception if unable to compute a result
*/
V call() throws Exception;
}Callable接口同样是一个函数式接口,只有一个抽象方法call(),异步任务逻辑同样在该方法中实现。与run()方法不同的是call()不近有返回值还可以抛出异常。
Callable无法直接通过Thread类来执行。Callable一般结合ExecutorService来提交执行,并结和Future来获取结果。
ExecutorService中提交任务的方法:
public interface ExecutorService extends Executor{
<T> Future<T> submit(Callable<T> task);
<T> Future<T> submit(Runnable task, T result);
Future<?> submit(Runnable task);
}这三个submit方法都是提交一个任务,返回值都是Future对象。可以通过Future对象来查询任务的状态,获取任务的最终结果,取消任务。