通过前面两篇文章,我们已经掌握了创建线程、运行、停止相关方法了,接下来我们继续学习线程的返回值,这样线程创建、运行、返回、终止的整个过程算是有个闭环了。
Runnable接口
Runnable接口是并发编程的核心接口之一,作用是定义线程执行的任务,将任务逻辑与线程的执行机制解耦。
@FunctionalInterface
public interface Runnable {
/**
* Runs this operation.
*/
void run();
}
接口中只有一个run()方法,该方法没有返回值,其设计同样遵循单一职责原则,实现了该接口表明具备运行线程任务的能力,Thread类同样实现了该接口。看下面一个简单的例子。
public class ThreadTask implements Runnable{
@Override
public void run() {
System.out.println(Thread.currentThread().getName()+" run");
}
public static void main(String[] args) {
Thread t = new Thread(new ThreadTask());
t.start();
}
}
上面的例子,线程t启动运行完后就完了,但是如果想要线程t运行完后返回一个变量,那该如何实现?
Callable接口
在jdk1.5之后,引入Callable接口来解决线程返回值的问题。
/**
* A task that returns a result and may throw an exception.
* Implementors define a single method with no arguments called
* {@code call}.
*
* <p>The {@code Callable} interface is similar to {@link
* java.lang.Runnable}, in that both are designed for classes whose
* instances are potentially executed by another thread. A
* {@code Runnable}, however, does not return a result and cannot
* throw a checked exception.
*
* <p>The {@link Executors} class contains utility methods to
* convert from other common forms to {@code Callable} classes.
*
* @see Executor
* @since 1.5
* @author Doug Lea
* @param <V> the result type of method {@code call}
*/
@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接口类似Runnable接口,同样是用来定义线程执行的任务,也是只有一个方法,但是Callable接口比Runnable接口多了两个功能,就是可以返回任意类型的返回值和可以抛出异常。需要注意的是Callable类型的任务对象并不能像Runnable类型的任务对象一样用,直接传入Thread类的构造函数创建线程,从前面的文章中我们得知Thread类的构造函数并没有Callable类型的参数。那Callable怎么用?线程返回结果用什么表示?我们接着往下看。
Future接口
Thread类只接收Runnable类型的任务但是没有返回值,Callable类型的任务有返回值但是不能往Thread类里面传。这不就是牛郎和织女隔着一条银河想相爱又不能靠近吗,给他们搭一座桥满足他们吧。面向对象程序设计就是这么人性化,总能在生活中找比喻的例子。Future与FutureTask的引入就是为了解决这一问题。Future接口也是在jdk1.5之后引入的,源码如下:
/**
* A {@code Future} represents the result of an asynchronous
* computation. Methods are provided to check if the computation is
* complete, to wait for its completion, and to retrieve the result of
* the computation. The result can only be retrieved using method
* {@code get} when the computation has completed, blocking if
* necessary until it is ready. Cancellation is performed by the
* {@code cancel} method. Additional methods are provided to
* determine if the task completed normally or was cancelled. Once a
* computation has completed, the computation cannot be cancelled.
* If you would like to use a {@code Future} for the sake
* of cancellability but not provide a usable result, you can
* declare types of the form {@code Future<?>} and
* return {@code null} as a result of the underlying task.
...
*
* @see FutureTask
* @see Executor
* @since 1.5
* @author Doug Lea
* @param <V> The result type returned by this Future's {@code get} method
*/
public interface Future<V> {
...
}
Future接口表示一个异步计算任务的返回结果,提供了检查任务是否完成、等待任务完成直到返回结果、取消任务执行、获取任务状态等方法。下面我们来学习下Future接口的属性和方法。

1、get()方法
/**
* Waits if necessary for the computation to complete, and then
* retrieves its result.
*
* @return the computed result
* @throws CancellationException if the computation was cancelled
* @throws ExecutionException if the computation threw an
* exception
* @throws InterruptedException if the current thread was interrupted
* while waiting
*/
V get() throws InterruptedException, ExecutionException;
调用get()方法将等待任务完成并返回结果,如果在等待任务完成的过程中任务被取消了将会抛出取消异常,如果任务执行过程出现异常将会抛出执行异常,如果在等待任务完成的过程中线程被中断,将会抛出中断异常。V get(long timeout, TimeUnit unit)方法可以指定等待指定时间,等待超时了还没有返回则抛出超时异常。
2、boolean cancel(boolean mayInterruptIfRunning)方法
/**
* Attempts to cancel execution of this task. This method has no
* effect if the task is already completed or cancelled, or could
* not be cancelled for some other reason. Otherwise, if this
* task has not started when {@code cancel} is called, this task
* should never run. If the task has already started, then the
* {@code mayInterruptIfRunning} parameter determines whether the
* thread executing this task (when known by the implementation)
* is interrupted in an attempt to stop the task.
*
* <p>The return value from this method does not necessarily
* indicate whether the task is now cancelled; use {@link
* #isCancelled}.
*
* @param mayInterruptIfRunning {@code true} if the thread
* executing this task should be interrupted (if the thread is
* known to the implementation); otherwise, in-progress tasks are
* allowed to complete
* @return {@code false} if the task could not be cancelled,
* typically because it has already completed; {@code true}
* otherwise. If two or more threads cause a task to be cancelled,
* then at least one of them returns {@code true}. Implementations
* may provide stronger guarantees.
*/
boolean cancel(boolean mayInterruptIfRunning);
调用该方法将试图去取消正在执行的任务,需要注意的是,如果任务还没有启动就调用该方法,那么任务将不会执行。如果任务已经启动了,传入的参数mayInterruptIfRunning将决定正在执行的线程是否可以被中断以便停止任务。
传入的mayInterruptIfRunning的值为true时,正在运行中的线程将被中断(如果已知线程已经执行完成),否则传入false时,进行中的任务应当允许完成。
如果任务不可以被取消那么将返回false,否则返回true。如果有多个线程同时取消了任务,那么至少有一个线程返回true。
综合上述,调用该方法只是试图去取消任务,并不能确定任务现在是已经被取消了,需要通过调用isCancelled()方法来判断,如果任务在正常的完成之前被取消了,那么该方法将返回true。
3、isDone()方法
/**
* Returns {@code true} if this task completed.
*
* Completion may be due to normal termination, an exception, or
* cancellation -- in all of these cases, this method will return
* {@code true}.
*
* @return {@code true} if this task completed
*/
boolean isDone();
判断任务是否已经完成。
4、resultNow()方法
/**
* Returns the computed result, without waiting.
*
* <p> This method is for ca

最低0.47元/天 解锁文章

被折叠的 条评论
为什么被折叠?



