JAVA多线程实现方式主要有三种:继承Thread类、实现Runnable接口、使用ExecutorService、Callable、Future实现有返回结果的多线程
一、Callable
Runnable和Callable的区别是:
(1)Callable的任务执行后可返回值,而Runnable的任务是不能返回值得
(2)call方法可以抛出异常,run方法不可以
源码如下:
/**
* <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.
*/
@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;
}
二、Future
Future就是对于具体的Runnable或者Callable任务的操作,可以取消、查询是否取消、是否完成、获取结果。
源码:
public interface Future<V> {
/**
* @param mayInterruptIfRunning 任务执行期间是否可以取消,true可以,false不可以
* @return 无论mayInterruptIfRunning true或false,只要任务已经执行完成则返回false,否则true
*/
boolean cancel(boolean mayInterruptIfRunning);
/**
* 任务执行之前或者正常完成之前被取消返回true
*/
boolean isCancelled();
/**
* 任务完成,返回true,被取消除外
*/
boolean isDone();
/**
* 获取执行结果,这个方法会产生阻塞,会一直等到任务执行完毕才返回;
*/
V get() throws InterruptedException, ExecutionException;
/**
* 用来获取执行结果,如果在指定时间内,还没获取到结果,就直接返回null。
*/
V get(long timeout, TimeUnit unit)
throws InterruptedException, ExecutionException, TimeoutException;
}
三、FutureTask
由上可知,Future是一个接口,没有具体的实现可以使用,FutureTask就是Future的实现:
RunnableFuture继承Runnable 、Future:
public interface RunnableFuture<V> extends Runnable, Future<V> {
/**
* Sets this Future to the result of its computation
* unless it has been cancelled.
*/
void run();
}
FutureTask类实现了RunnableFuture接口:
public class FutureTask<V> implements RunnableFuture<V> {
}
FutureTask的构造函数:
public FutureTask(Callable<V> callable) {
if (callable == null)
throw new NullPointerException();
this.callable = callable;
this.state = NEW; // ensure visibility of callable
}
public FutureTask(Runnable runnable, V result) {
this.callable = Executors.callable(runnable, result);
this.state = NEW; // ensure visibility of callable
}
FutureTask的run方法
public void run() {
if (state != NEW ||
!UNSAFE.compareAndSwapObject(this, runnerOffset,
null, Thread.currentThread()))
return;
try {
Callable<V> c = callable;
if (c != null && state == NEW) {
V result;
boolean ran;
try {
result = c.call();
ran = true;
} catch (Throwable ex) {
result = null;
ran = false;
setException(ex);
}
if (ran)
set(result);
}
} finally {
// runner must be non-null until state is settled to
// prevent concurrent calls to run()
runner = null;
// state must be re-read after nulling runner to prevent
// leaked interrupts
int s = state;
if (s >= INTERRUPTING)
handlePossibleCancellationInterrupt(s);
}
}
如果任务执行成功,则把返回结果set(V v)方法存储,方法如下:
protected void set(V v) {
if (UNSAFE.compareAndSwapInt(this, stateOffset, NEW, COMPLETING)) {
outcome = v;
UNSAFE.putOrderedInt(this, stateOffset, NORMAL); // final state
finishCompletion();
}
}
若执行发生异常,则调用setException()方法保存异常信息,方法如下:
protected void setException(Throwable t) {
if (UNSAFE.compareAndSwapInt(this, stateOffset, NEW, COMPLETING)) {
outcome = t;
UNSAFE.putOrderedInt(this, stateOffset, EXCEPTIONAL); // final state
finishCompletion();
}
}
获取结果则是get()方法,如下:
public V get() throws InterruptedException, ExecutionException {
int s = state;
if (s <= COMPLETING)
s = awaitDone(false, 0L);
return report(s);
}
具体结果返回是通过report()方法操作:
private V report(int s) throws ExecutionException {
Object x = outcome;
if (s == NORMAL)
return (V)x;
if (s >= CANCELLED)
throw new CancellationException();
throw new ExecutionException((Throwable)x);
}
如果state的状态为NORMAL,返回计算后的值;如果state的状态大于等于CANCELLED,说明任务被成功取消执行、或响应中断,则返回CancellationException异常,否则返回ExecutionException异常。
四、使用
Future、FutureTask的使用要配合Excutor的使用,ExecutorService中的submit方法接受一个Runnable或者Callable,然后返回一个Future来获得任务的执行结果或者取消任务。
public interface ExecutorService extends Executor {
<T> Future<T> submit(Callable<T> task);
Future<?> submit(Runnable task);
}
例子:
public static void main(String[] arg){
ExecutorService executor = Executors. newCachedThreadPool();
FutureTask<Integer> futureTask = new FutureTask<Integer>(new Callable<Integer>() {
@Override
public Integer call() throws Exception {
return 1;
}
});
Future f =executor.submit(futureTask);
Future f1 =executor.submit(new Callable<Integer>() {
@Override
public Integer call() throws Exception {
return 2;
}
});
executor.shutdown();
try {
Thread. sleep(1000);
} catch (InterruptedException e1) {
e1.printStackTrace();
}
System. out.println("主线程在执行任务" );
try {
System. out.println("task运行结果" + futureTask.get());
System. out.println("task运行结果" + f.get());
System. out.println("task运行结果" + f1.get());
} catch (InterruptedException e) {
e.printStackTrace();
} catch (ExecutionException e) {
e.printStackTrace();
}
System. out.println("所有任务执行完毕" );
}
注:FutureTask 在submit的时候不需要返回future对象,自己就可以get到结果,Callable Runnable需要返回Future才能获取结果;
这段代码中返回的Future是新建的对象,FutureTask为什么结果值不是在返回的对象之中呢?
public Future<?> submit(Runnable task) {
if (task == null) throw new NullPointerException();
RunnableFuture<Void> ftask = newTaskFor(task, null);
execute(ftask);
return ftask;
}
protected <T> RunnableFuture<T> newTaskFor(Runnable runnable, T value) {
return new FutureTask<T>(runnable, value);
}
通过这段代码我们可以知道,直接传入FutureTask会被当做Runnable对象进行处理,继续深入就会发现FutureTask会被RunnableAdapter进行适配,我们在外层的Future是无法获取返回结果的,但是其内部的FutureTask是有返回值的。