当前位置: 代码迷 >> 综合 >> Java 使用 Callable 接口创建线程
  详细解决方案

Java 使用 Callable 接口创建线程

热度:27   发布时间:2023-12-26 12:47:36.0

使用 Callable 接口创建线程相较于实现 Runnable 接口方式的优点:可以有返回值,可以抛出异常。

 1. 概述

Callable 接口的源码如下所示:@FunctionalInterface 表名是一个函数式的接口,可以有返回值 V (泛型),可以抛出异常 throws Exception。call 方法类似  Runnable 接口 中的 run 方法,作为线程的 执行体。

@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;
}

2. FutureTask

FutureTask 类实现 RunnableFuture接口。

public class FutureTask<V> implements RunnableFuture<V> 

 RunnableFuture接口 实现 Runnable 和 Future。

public interface RunnableFuture<V> extends Runnable, Future<V> {void run();
}

 FutureTask 的 run 方法调用 call 方法 ,等待  call 方法  执行完毕,存储 call 方法的返回值,然后  FutureTask  可以通过 get 方法 获取  call 方法的返回值。接下来看一下 FutureTask 的 源码。

 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(); // 调用 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 interruptsint s = state;if (s >= INTERRUPTING)handlePossibleCancellationInterrupt(s);}}

 set 方法如下所示,使用 CAS(乐观锁的一种形式) 设置返回值到outcome。

    protected void set(V v) {if (UNSAFE.compareAndSwapInt(this, stateOffset, NEW, COMPLETING)) {outcome = v;UNSAFE.putOrderedInt(this, stateOffset, NORMAL); // final statefinishCompletion();}}

 get 方法获取 outcome。

    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);}

3. 代码示例

重写 call 方法:

    @Overridepublic Integer call() throws Exception {int times = 1000;for (int i=0; i<times; i++) {if(i%100 == 0)System.out.println(Thread.currentThread().getName());}return times;}

 使用 FutureTask 类包装 Callable 接口的实现类。

 FutureTask<Integer> task = new FutureTask<Integer>(new MyCallableStudy());

启动线程。

new Thread(task, "callable").start();

获取返回值。

task.get();

完整代码如下所示: 

package callable;import java.util.concurrent.*;public class MyCallableStudy implements Callable<Integer> {@Overridepublic Integer call() throws Exception {int times = 1000;for (int i=0; i<times; i++) {if(i%100 == 0)System.out.println(Thread.currentThread().getName());}return times;}public static void main(String[] args) throws ExecutionException, InterruptedException {FutureTask<Integer> task = new FutureTask<Integer>(new MyCallableStudy());new Thread(task, "callable").start();System.out.println(task.get());}
}

运行截图:

  相关解决方案